- Go 62.9%
- TypeScript 35.7%
- CSS 0.7%
- Dockerfile 0.3%
- Shell 0.3%
| cmd/server | ||
| docker | ||
| internal | ||
| webapp | ||
| .gitignore | ||
| docker-compose.yml | ||
| README.md | ||
GPB
GPB is a self-hosted Google Photos Backup control plane.
It provides a web dashboard for managing users, paired Android nodes, file activity, backup settings, logs, and runtime controls. Files can be ingested through Telegram, WebDAV, or SFTP, then queued for deduplication, node sync, verification, and cleanup.
Features
- React + Vite web control panel
- Go backend with Gin
- SQLite database stored in
data/gpb/gpb.db - File uploads stored in
data/uploads - Web dashboard authentication with session cookies
- Admin and user management
- Node pairing through QR/token flow
- File activity dashboard with status filters
- Retry failed uploads and jobs
- WebDAV ingestion endpoint
- SFTP ingestion endpoint
- Optional Telegram bot ingestion
- Optional local
telegram-bot-apiruntime - Server-Sent Events for live UI updates
- Health and readiness endpoints
- Docker Compose deployment with Traefik labels
Tech Stack
Backend
- Go
- Gin
- GORM
- SQLite
- WebDAV
- SFTP server
- Telegram Bot API integration
Frontend
- React 18
- TypeScript
- Vite
- Tailwind CSS
- TanStack Query
- React Router
- Framer Motion
- Lucide Icons
- React QR Code
Repository Structure
.
├── cmd/
│ └── server/ # Backend entrypoint
├── docker/
│ ├── Dockerfile # Multi-stage frontend/backend/runtime image
│ ├── example.env # Example environment file
│ └── start.sh # Container startup script
├── internal/
│ ├── adapters/ # DB, HTTP v3, WebDAV, SFTP, event bus adapters
│ ├── core/ # Domain models and ports
│ ├── service/ # Ingest, node, sync services
│ └── web/ # Web handlers, middleware, React serving
├── webapp/ # React control panel
├── data/ # Runtime data, ignored by git
├── docker-compose.yml
└── README.md
Deployment
1. Clone the repository
git clone <your-repo-url>
cd <repo-name>
2. Create the environment file
cp docker/example.env docker/.env
Edit docker/.env:
TELEGRAM_API_ID=
TELEGRAM_API_HASH=
ADMIN_USERNAME=admin
ADMIN_PASSWORD=change-this-password
ADMIN_TELEGRAM_USER_ID=
SESSION_SECRET=change-this-to-a-long-random-secret
TELEGRAM_BOT_TOKEN=
DOMAIN_NAME=gpb.example.com
FORCE_SECURE_COOKIES=true
Generate a strong session secret:
openssl rand -hex 32
3. Create the external Traefik network
The compose file expects an existing Docker network named traefik_network.
docker network create traefik_network
Skip this command if the network already exists.
4. Update domains
By default, the compose file uses:
gpb.dtecx.dev
dav.dtecx.dev
Change these Traefik labels in docker-compose.yml to your own domains:
- "traefik.http.routers.gpb-ui.rule=Host(`gpb.example.com`)"
- "traefik.http.routers.gpb-webdav.rule=Host(`dav.example.com`)"
Also update:
DOMAIN_NAME=gpb.example.com
5. Start the stack
docker compose up -d --build
6. Check logs
docker logs -f gpb-backend
7. Check health
From inside the server:
curl http://127.0.0.1/readyz
Expected response:
{"ok":true}
Services and Ports
| Service | Internal Port | External Exposure | Purpose |
|---|---|---|---|
| Web UI / API | 80 |
Traefik | React app and backend API |
| WebDAV | 8080 |
Traefik | WebDAV file ingestion |
| SFTP | 2222 |
Host port 2222 |
SFTP file ingestion |
| Local Telegram Bot API | 8089 |
Internal only | Optional local Telegram API runtime |
Runtime Data
Runtime data is stored in:
data/
├── gpb/
│ └── gpb.db
├── uploads/
├── sftp/
│ └── host_rsa
└── telegram-bot-api/
The data/ directory is ignored by git and mounted into the container as:
./data:/app/data
Environment Variables
| Variable | Required | Description |
|---|---|---|
ADMIN_USERNAME |
Recommended | Bootstrap admin username |
ADMIN_PASSWORD |
Recommended | Bootstrap admin password |
ADMIN_TELEGRAM_USER_ID |
Optional | Telegram ID for the admin user |
SESSION_SECRET |
Yes | Secret used for session cookie signing |
DOMAIN_NAME |
Recommended | Public web domain, used for secure cookie behavior |
FORCE_SECURE_COOKIES |
Recommended | Set to true for HTTPS deployments |
TELEGRAM_BOT_TOKEN |
Optional | Enables Telegram bot ingestion |
TELEGRAM_API_ID |
Optional | Enables local telegram-bot-api mode |
TELEGRAM_API_HASH |
Optional | Enables local telegram-bot-api mode |
If TELEGRAM_API_ID and TELEGRAM_API_HASH are not set, the bot uses the public Telegram Bot API.
Web UI
Open:
https://gpb.example.com
The UI includes:
- Dashboard
- File activity
- Node/fleet overview
- Settings
- Admin user management
- Logs
- Pairing QR code generation
- Runtime controls
The app loads a custom logo from:
/gpb-logo.png
Place your logo in the frontend public assets so it is included in the final Vite build.
API Overview
Health
GET /healthz
GET /readyz
Web API
POST /api/web/auth/login
GET /api/web/auth/me
POST /api/web/auth/logout
GET /api/web/dashboard
GET /api/web/files
GET /api/web/files/stats
POST /api/web/files/retry-failed
GET /api/web/nodes
GET /api/web/events
GET /api/web/settings
PUT /api/web/settings/profile
PUT /api/web/settings/account
GET /api/web/settings/accounts
GET /api/web/node/pairing-qr
Admin API
GET /api/web/admin/users
POST /api/web/admin/users
GET /api/web/admin/logs
PUT /api/web/admin/node-policy
PUT /api/web/admin/server-policy
POST /api/web/admin/toggle-servers
POST /api/web/admin/toggle-node-service
POST /api/web/admin/clear-db
POST /api/web/admin/clear-failed
POST /api/web/admin/nuke-runtime
DELETE /api/web/admin/nodes/:id
Node API v3
POST /api/v3/node/pair
POST /api/v3/node/unpair
POST /api/v3/node/sync
GET /api/v3/files/:id/content
WebDAV
WebDAV is exposed through the separate WebDAV server port.
With the default compose labels:
https://dav.example.com
Authentication uses GPB user credentials.
SFTP
SFTP is exposed directly on port 2222.
Example:
sftp -P 2222 username@your-server-ip
Authentication uses GPB user credentials.
Uploaded files are ingested into the GPB pipeline and associated with the authenticated user.
Frontend Development
Install dependencies:
cd webapp
npm install
Start Vite:
npm run dev
Build frontend:
npm run build
The frontend expects the backend API to be available on the same origin in production. For local frontend-only development, run the backend separately or add a Vite proxy if needed.
Docker Build
The production image is built in three stages:
- Node builder builds the React/Vite frontend.
- Go builder compiles the backend server.
- Runtime image includes:
gpb-server- built frontend assets
- startup script
- optional
telegram-bot-apibinary
Manual build:
docker compose build
Run:
docker compose up -d
Security Notes
Change these before exposing the service publicly:
ADMIN_PASSWORD=
SESSION_SECRET=
DOMAIN_NAME=
FORCE_SECURE_COOKIES=true
Do not use the default bootstrap password in production.
The app sets secure session cookie behavior when FORCE_SECURE_COOKIES=true or when DOMAIN_NAME is a non-localhost domain.
Backup
Back up the data/ directory:
tar -czf gpb-backup.tar.gz data/
Restore by placing the directory back before starting the container:
tar -xzf gpb-backup.tar.gz
docker compose up -d
Useful Commands
Start:
docker compose up -d
Rebuild:
docker compose up -d --build
Stop:
docker compose down
View logs:
docker logs -f gpb-backend
Shell into container:
docker exec -it gpb-backend sh
Check database files:
ls -lah data/gpb
Check uploads:
ls -lah data/uploads
Git Ignore Notes
The repository ignores:
data/
.env
.env.*
getcode.py
*.txt
This keeps runtime data, secrets, and temporary code-dump files out of git.