Files
ServerKit/docs/DEPLOYMENT.md
T
Juan DenisandClaude Opus 4.8 ca66629780 feat(deploy): serve panel frontend from host nginx, retire the container
The panel is now fully off Docker: the React SPA is served as static
files directly by host nginx from frontend/dist, eliminating the
serverkit-frontend container and the double nginx hop (host nginx ->
container nginx -> dist). Docker is now used ONLY for managed app
workloads.

- nginx sites (serverkit.conf + serverkit-insecure.conf): `location /`
  now roots at /opt/serverkit/frontend/dist with a try_files SPA
  fallback and a long-cache /assets/ block, instead of proxying
  127.0.0.1:3847. Root tracks the /opt/serverkit symlink so blue/green
  updates swap assets atomically.
- install.sh: launch_services no longer builds/starts a frontend
  container; adds apply_frontend_root (rewrites the dist root for a
  custom SERVERKIT_DIR) and selinux_label_frontend_dist (httpd_sys_-
  content_t so SELinux hosts can read the bundle from /opt).
- update.sh: refresh_config carries the same root rewrite across
  upgrades; selinux_label_dist relabels the switched-in slot; dropped
  the `docker compose up -d --force-recreate frontend` from both the
  forward and rollback paths.
- docker-compose.yml: frontend service moved behind a `legacy-frontend`
  profile (opt-in escape hatch); default `up -d` starts nothing.
- docs/DEPLOYMENT.md: documents the off-Docker panel model.

Tests: T14 (refresh_config rewrites dist root for custom install dir),
T15 (shipped nginx configs serve static, never proxy :3847). 16 passed.

Note: live nginx -t / SELinux file-serving not validated on a RHEL box
from this dev host; logic is best-effort guarded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 02:24:22 -04:00

407 lines
9.4 KiB
Markdown

# ServerKit Deployment Guide
Complete guide for deploying ServerKit on Ubuntu servers.
## Deployment model (important)
ServerKit's backend **manages the host it runs on** — it creates app
directories under `/var/serverkit/apps`, drives the host Docker daemon (one
container per managed app), reloads nginx, and runs systemctl/firewall/PHP-FPM.
A backend running *inside a container* cannot do any of that. So the canonical
deployment installed by `./serverkit install` (`install.sh`) runs **fully off
Docker for the panel itself**:
- the **backend on the host** via systemd (`serverkit.service`), and
- the **frontend as static files served directly by host nginx** from
`frontend/dist` (built by `install.sh`) — no container. Host nginx serves the
SPA at `location /` and proxies `/api` + `/socket.io` to the host backend on
`:5000`.
Docker is therefore used **only for the workloads you host** (one container per
managed app). This is deliberate: a ServerKit update never touches those
containers, and host nginx — which reverse-proxies them — is only ever
*reloaded*, never stopped, so updating the panel causes **zero downtime for
hosted apps**.
Do **not** add the backend into Docker — a containerized backend fails
app/WordPress creation with `Permission denied: /var/serverkit/apps/...` and has
no access to the host Docker daemon. A containerized *frontend* is still
available as an opt-in escape hatch (`docker compose --profile legacy-frontend
up -d`, plus repointing nginx `location /` at `127.0.0.1:3847`) but is not used
by the default install. The single-container image in `./Dockerfile` exists only
for throwaway demos and, as its header states, cannot manage the host.
## Quick Install (Ubuntu)
```bash
# One-line install
curl -fsSL https://serverkit.ai/install.sh | bash
# Or clone and install manually
git clone https://github.com/jhd3197/serverkit.git
cd serverkit
chmod +x serverkit
./serverkit install
```
## Prerequisites
- Ubuntu 20.04+ (or Debian 11+)
- Docker 20.10+ and Docker Compose 2.0+
- At least 1GB RAM
- Domain name (for SSL/HTTPS)
## CLI Commands
ServerKit includes a management CLI for common administrative tasks.
### Service Management
```bash
# Start/Stop/Restart
serverkit start
serverkit stop
serverkit restart
# View status
serverkit status
# View logs
serverkit logs # All services
serverkit logs backend # Backend only
serverkit logs frontend # Frontend only
# Update to latest version
serverkit update
# Uninstall
serverkit uninstall
```
### User Management
```bash
# Create admin user
serverkit create-admin
# Prompts for: email, username, password
# Reset a user's password
serverkit reset-password
# Prompts for: email, new password
# Unlock a locked account (after failed login attempts)
serverkit unlock-user
# Prompts for: email
# List all users
serverkit list-users
# Promote user to admin
serverkit make-admin
# Prompts for: email
# Deactivate/Activate user
serverkit deactivate-user
serverkit activate-user
```
### Database Management
```bash
# Initialize database
serverkit init-db
# Apply database migrations (after updates)
serverkit migrate-db
# Backup database
serverkit backup-db
# Creates: backup/serverkit-YYYYMMDD-HHMMSS.db
# Restore from backup
serverkit restore-db backup/serverkit-20240115-120000.db
```
### App & Cleanup Commands
```bash
# List all installed applications (from database)
serverkit list-apps
# Also show all Docker containers (including infrastructure)
serverkit list-apps --all
# Delete all apps, containers, folders, and orphaned Docker resources
serverkit cleanup-apps
# Also delete Docker volumes
serverkit cleanup-apps --delete-volumes
# Keep database records (only delete containers/folders)
serverkit cleanup-apps --keep-db
# Complete factory reset (delete everything and start fresh)
# Preserves only serverkit-frontend infrastructure
serverkit factory-reset
```
**Note:** Cleanup commands will:
- Stop and remove all app containers
- Remove orphaned Docker containers (not tracked in database)
- Prune unused Docker networks
- Delete all folders in `/var/serverkit/apps/`
- Never touch ServerKit infrastructure (serverkit-frontend, serverkit-network)
### Utility Commands
```bash
# Generate secure keys for .env
serverkit generate-keys
# Edit configuration
serverkit config
# Open shell in backend container
serverkit shell
# Show help
serverkit help
```
## Manual Installation
### 1. Install Docker
```bash
# Install Docker
curl -fsSL https://get.docker.com | sh
# Add user to docker group
sudo usermod -aG docker $USER
# Log out and back in, then verify
docker --version
```
### 2. Clone Repository
```bash
git clone https://github.com/jhd3197/serverkit.git /opt/serverkit
cd /opt/serverkit
```
### 3. Configure Environment
```bash
# Generate secure keys
serverkit generate-keys
# Create .env file
cat > .env << 'EOF'
SECRET_KEY=<paste-generated-key>
JWT_SECRET_KEY=<paste-generated-key>
DATABASE_URL=sqlite:///serverkit.db
CORS_ORIGINS=https://yourdomain.com
PORT=80
SSL_PORT=443
FLASK_ENV=production
EOF
```
### 4. SSL Certificate Setup
#### Option A: Let's Encrypt (Recommended)
```bash
# Install certbot
sudo apt install certbot
# Get certificate (stop any service on port 80 first)
sudo certbot certonly --standalone -d yourdomain.com
# Copy certificates
sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem nginx/ssl/
sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem nginx/ssl/
sudo chown -R $USER:$USER nginx/ssl/
```
#### Option B: Self-Signed (Development Only)
```bash
mkdir -p nginx/ssl
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout nginx/ssl/privkey.pem \
-out nginx/ssl/fullchain.pem \
-subj "/CN=localhost"
```
### 5. Build and Start
Both panel tiers run on the host: the backend under systemd
(`serverkit.service`) and the frontend as static files served by host nginx from
`frontend/dist`. `./serverkit install` builds the bundle and wires nginx for
you. See the **Deployment model** note above.
```bash
# Build the SPA bundle host nginx serves (install.sh does this automatically)
cd frontend && npm ci && npm run build && cd ..
# Start the host backend + nginx
sudo systemctl start serverkit
sudo systemctl reload nginx
# Verify
serverkit status
```
### 6. Create Admin User
```bash
serverkit create-admin
```
## Systemd Service
Run ServerKit as a system service:
```bash
# Copy service file
sudo cp deploy/serverkit.service /etc/systemd/system/
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable serverkit
sudo systemctl start serverkit
# Check status
sudo systemctl status serverkit
```
## Configuration Reference
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `SECRET_KEY` | Flask secret key | Required |
| `JWT_SECRET_KEY` | JWT signing key | Required |
| `DATABASE_URL` | Database connection string | `sqlite:///serverkit.db` |
| `CORS_ORIGINS` | Allowed CORS origins | `http://localhost` |
| `PORT` | HTTP port | `80` |
| `SSL_PORT` | HTTPS port | `443` |
| `FLASK_ENV` | Environment mode | `production` |
### Host data locations
The backend runs on the host, so its data lives on the host filesystem (not in
Docker volumes):
| Path | Purpose |
|------|---------|
| `/opt/serverkit/backend/instance/serverkit.db` | SQLite database (default) |
| `/var/serverkit/apps/` | Managed app directories (one per app) |
| `/etc/serverkit/` | Config (templates, ssl-mode, install state) |
| `/var/backups/serverkit/` | Backups |
## Common Tasks
### Auto-renew SSL Certificate
```bash
# Add to crontab
sudo crontab -e
# Add this line (renews at 2:30 AM daily)
30 2 * * * certbot renew --quiet && cp /etc/letsencrypt/live/yourdomain.com/*.pem /opt/serverkit/nginx/ssl/ && docker compose -f /opt/serverkit/docker-compose.yml restart frontend
```
### Change Domain
1. Update `.env` file: `CORS_ORIGINS=https://newdomain.com`
2. Get new SSL certificate
3. Restart: `serverkit restart`
### Scale for Production
For high-traffic deployments, consider:
```bash
# Use PostgreSQL instead of SQLite
DATABASE_URL=postgresql://user:pass@localhost:5432/serverkit
# Add Redis for session storage
# Edit docker-compose.yml to add redis service
```
## Troubleshooting
### Container won't start
```bash
# Check logs
serverkit logs backend
# Rebuild
docker compose build --no-cache
docker compose up -d
```
### Permission denied errors
```bash
# Fix Docker socket permissions
sudo chmod 666 /var/run/docker.sock
# Or add user to docker group
sudo usermod -aG docker $USER
# Then log out and back in
```
### Port already in use
```bash
# Find what's using port 80
sudo lsof -i :80
# Stop the service or change PORT in .env
```
### Reset everything
```bash
# Stop and remove all containers and volumes
serverkit stop
docker compose down -v
# Rebuild from scratch
docker compose build --no-cache
serverkit start
serverkit init-db
serverkit create-admin
```
### Locked out / Forgot password
```bash
# Reset password via CLI
serverkit reset-password
# Enter email and new password
# Or unlock account if locked
serverkit unlock-user
```
## Security Checklist
- [ ] Generated unique SECRET_KEY and JWT_SECRET_KEY
- [ ] Using HTTPS with valid SSL certificate
- [ ] Firewall configured (allow only ports 80, 443, 22)
- [ ] Regular backups configured
- [ ] Admin password is strong
- [ ] Updated to latest version
## Support
- GitHub Issues: https://github.com/jhd3197/serverkit/issues
- Documentation: https://github.com/jhd3197/serverkit/wiki