Files
RenewCMS/docs/deployment.md
T

4.8 KiB

Deployment

RenewCMS ships as one self-contained executable. It serves:

Path What
/v1/* JSON API
/healthz Liveness check, returns 200 ok
/* The Vue SPA (embedded), with fallback to index.html for client-side routes

Its only runtime state is the SQLite database (DB_FILE) and the uploads directory (UPLOAD_DIR). Nothing else needs to be installed on the server.

1. Build

On any machine with the dev prerequisites:

task build     # this OS/arch → bin/renewcms[.exe]
task release   # all targets  → bin/renewcms_<version>_<os>_<arch>[.exe]

The frontend is built once and embedded into every binary. The binaries are static (CGO_ENABLED=0), so a Linux build runs on any distribution. The version comes from git describe: tag a release (git tag v1.2.0) before building, and the binary logs its version at startup.

2. Lay out the server

The following is a suggested layout for Linux:

/opt/renewcms/renewcms          the binary
/etc/renewcms/renewcms.env      configuration (chmod 600, owned by root)
/var/lib/renewcms/              data: renewcms.db, uploads/  (owned by the service user)
sudo useradd --system --home /var/lib/renewcms --shell /usr/sbin/nologin renewcms
sudo install -d -o renewcms -g renewcms /var/lib/renewcms
sudo install -D -m 755 bin/renewcms_v1.2.0_linux_amd64 /opt/renewcms/renewcms
sudo install -D -m 600 /dev/null /etc/renewcms/renewcms.env   # then edit it

/etc/renewcms/renewcms.env looks like this (see configuration.md for every variable):

ENVIRONMENT=production
PUBLIC_URL=https://cms.example.com
PORT=8080
DB_FILE=/var/lib/renewcms/renewcms.db
UPLOAD_DIR=/var/lib/renewcms/uploads
JWT_SECRET=<openssl rand -hex 32>
SMTP_EMAIL=noreply@example.com
SMTP_PASSWORD=...
SMTP_HOST=smtp.example.com
SMTP_PORT=465

3. Run it as a service (systemd)

/etc/systemd/system/renewcms.service:

[Unit]
Description=RenewCMS
After=network-online.target
Wants=network-online.target

[Service]
User=renewcms
Group=renewcms
WorkingDirectory=/var/lib/renewcms
EnvironmentFile=/etc/renewcms/renewcms.env
ExecStart=/opt/renewcms/renewcms
Restart=on-failure
# RenewCMS shuts down gracefully on SIGTERM (up to 10 s to finish requests and close the DB)
TimeoutStopSec=15

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/renewcms

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now renewcms
journalctl -u renewcms -f
curl -fsS http://localhost:8080/healthz

On Windows, register the binary as a service with a wrapper such as NSSM or WinSW, and set the same environment variables.

4. Put HTTPS in front

With ENVIRONMENT=production the auth cookie is Secure, so the site must be served over HTTPS. Terminate TLS in a reverse proxy and keep RenewCMS on localhost.

Caddy handles certificates automatically:

cms.example.com {
	reverse_proxy localhost:8080 {
		header_up X-Real-IP {remote_host}
	}
}

nginx:

server {
    listen 443 ssl http2;
    server_name cms.example.com;
    # ssl_certificate ... (e.g. certbot)

    client_max_body_size 20m;   # image uploads

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

If RenewCMS runs on the same host as the proxy, consider firewalling port 8080.

Either way, set TRUSTED_PROXIES (see configuration.md) to the proxy's own address as seen by RenewCMS, typically 127.0.0.1 when the proxy and RenewCMS share a host, so the login/password-reset rate limiter honors the forwarded client IP instead of the proxy's own address.

Backups

Everything worth backing up is under the data directory. Take a consistent SQLite copy while the service is running:

sqlite3 /var/lib/renewcms/renewcms.db ".backup '/backups/renewcms-$(date +%F).db'"
rsync -a /var/lib/renewcms/uploads/ /backups/uploads/

Alternatively, run systemctl stop renewcms, copy the directory, and run systemctl start renewcms.

Upgrading

  1. Back up (see above). The schema is migrated automatically at startup (GORM AutoMigrate), and there is no down-migration.
  2. Replace /opt/renewcms/renewcms with the new binary.
  3. Run sudo systemctl restart renewcms, then check journalctl -u renewcms for the new version line.

To roll back, put the previous binary back and restore the database backup if the schema changed.