- HTML 64.2%
- Go 34.5%
- Shell 1.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
A password-protected family tree web app (Go). History before this commit was dropped because it contained the login digest. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| health.go | ||
| health_test.go | ||
| index.html | ||
| LICENSE | ||
| main.go | ||
| main_test.go | ||
| README.md | ||
| restore.go | ||
| setup-nginx.sh | ||
Family Tree Application
A server-backed family tree application with Go backend, automatic backups, and password authentication.
Features
- Server-backed storage: All data stored on the server (no more localStorage)
- Password authentication: bcrypt password hash supplied via the environment, random session tokens
- Automatic backups: Smart backup rotation system
- Keeps backups for 365 days
- Maximum 2 backups from today
- Maximum 2 backups from the past week
- Maximum 2 backups from the past month
- Maximum 2 backups from the past year
- Flat file storage: Simple JSON file storage with easy restoration
- Beautiful old-fashioned design: Beige/neutral colors with serif fonts
- Reverse proxy ready: Nginx configuration included
Setup Instructions
1. Prerequisites
- Go 1.21 or later
- Nginx (for reverse proxy)
- Certbot (for SSL)
2. Install Dependencies
cd /home/satya/family-tree
go mod download
3. Build and Run the Application
# Build, vet and test (restore.go is a separate `go run` tool, excluded by a build tag)
go build -o family .
go vet ./...
go test -race ./...
# Generate a password hash (prompts for the password, prints a bcrypt hash)
./family -hash-password
# Run the application (it will listen on 127.0.0.1:8080 by default)
FAMILY_PASSWORD_HASH='<hash from above>' ./family
The server refuses to start unless FAMILY_PASSWORD_HASH is set. It accepts a
bcrypt hash ($2a$/$2b$/$2y$) or, for the transition from older versions,
a legacy hex SHA-256 digest of the password.
The application will automatically create:
data/directory for storing the family tree datadata/backups/directory for automatic backups
4. Set up Nginx Reverse Proxy
# Run the setup script (requires sudo)
sudo ./setup-nginx.sh
This will:
- Install Nginx if not already installed
- Install Certbot for SSL certificates
- Copy the Nginx configuration
- Enable the site
- Test and reload Nginx
5. Set up SSL with Certbot
Make sure DNS for family.benson.earth points to your server (both IPv4 and IPv6), then run:
sudo certbot --nginx -d family.benson.earth
Certbot will automatically:
- Obtain an SSL certificate from Let's Encrypt
- Update the Nginx configuration
- Set up automatic renewal
6. Run as a Service (Optional but Recommended)
Create a systemd service file:
sudo nano /etc/systemd/system/family.service
Add the following content:
[Unit]
Description=Family Tree Application
After=network.target
[Service]
Type=simple
User=satya
WorkingDirectory=/home/satya/family-tree
EnvironmentFile=/etc/family/family.env
ExecStart=/usr/local/bin/family
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
Enable and start the service:
Install the binary and the password hash (the env file should be root:root, mode 0600):
sudo install -m 0755 family /usr/local/bin/family
sudo install -d -m 0755 /etc/family
echo "FAMILY_PASSWORD_HASH=$(/usr/local/bin/family -hash-password)" | sudo tee /etc/family/family.env >/dev/null
sudo chmod 0600 /etc/family/family.env
sudo systemctl daemon-reload
sudo systemctl enable family
sudo systemctl start family
sudo systemctl status family
Usage
Accessing the Application
Visit https://family.benson.earth in your browser. You'll be prompted for the password.
Changing the Password
/usr/local/bin/family -hash-password # prompts for the new password, prints a bcrypt hash
sudoedit /etc/family/family.env # set FAMILY_PASSWORD_HASH=<printed hash>
sudo systemctl restart family
Restarting the service also signs everyone out (tokens are kept in memory).
Restoring from Backup
List all available backups:
go run restore.go list
Restore from a specific backup:
go run restore.go restore backup_2025-10-14_12-30-00.json
The restore tool will automatically create a pre-restore backup before restoring.
Manual Backup
Backups are created automatically every time you save changes. You can also manually copy the data file:
cp data/family-tree.json data/backups/manual-backup-$(date +%Y-%m-%d_%H-%M-%S).json
API Endpoints
-
POST /api/auth- Authenticate and get a token- Body:
{"passwordHash": "sha256-hash"} - Response:
{"success": true, "token": "token-string"}
- Body:
-
GET /api/members- Get all family members (requires authentication)- Header:
Authorization: Bearer <token> - Response: Array of family member objects
- Header:
-
POST /api/members- Save family members (requires authentication)- Header:
Authorization: Bearer <token> - Body: Array of family member objects
- Header:
-
GET /export- Download the family tree JSON (requires authentication)- Header:
Authorization: Bearer <token>
- Header:
Only / serves the public frontend (/index.html redirects to it). The page is
embedded in the binary, so editing index.html takes a rebuild and redeploy. The
application does not serve source files, Git metadata, data files, or backup
directories directly.
GET /health (no authentication; nginx blocks it from outside) reports the
commit the binary was built from and fails if data/family-tree.json is missing.
Tests can be run with go test -race ./... (the standalone restore.go
utility is excluded from the package build by a //go:build ignore tag).
Directory Structure
family-tree/
├── main.go # Main Go server
├── restore.go # Backup restoration utility
├── go.mod # Go module file
├── index.html # Frontend HTML/CSS/JS
├── nginx.conf # Nginx configuration
├── setup-nginx.sh # Nginx setup script
├── README.md # This file
└── data/
├── family-tree.json # Main data file
└── backups/ # Automatic backups directory
Troubleshooting
Application won't start
- Check if port 8080 is already in use:
sudo lsof -i :8080 - Check the logs if running as a service:
sudo journalctl -u family -f
Can't access via domain
- Verify DNS is pointing to your server:
dig family.benson.earth - Check Nginx is running:
sudo systemctl status nginx - Check Nginx logs:
sudo tail -f /var/log/nginx/family-tree_error.log
SSL certificate issues
- Re-run certbot:
sudo certbot --nginx -d family.benson.earth - Check certificate status:
sudo certbot certificates
Security Notes
- The password is hashed with SHA-256 on the client before being sent to the server;
the server compares that digest against a bcrypt hash from
FAMILY_PASSWORD_HASH - Authentication tokens are 32 random bytes and expire after 24 hours
- All traffic is encrypted with SSL/TLS
- Backups are stored locally on the server
- Consider setting up firewall rules to restrict access to port 8080 (only allow localhost)
License
Private family use only.