Start
Configuration
The panel reads its configuration from /opt/server-manager/.env. This page lists every setting, then covers putting the panel on its own domain with HTTPS.
The .env file
The file is passed to the container by Docker Compose and holds the admin and MySQL credentials, so keep it chmod 600 and never commit it. These values are never returned by the panel's API. After editing, apply the changes with docker compose up -d.
| Variable | Default | Purpose |
|---|---|---|
SM_ADMIN_EMAIL | — | Login email. |
SM_ADMIN_PASSWORD | — | Login password, plain text or a bcrypt hash ($2y$…). Generate a hash with htpasswd -bnBC 12 "" 'your-pass' | tr -d ':\n'. |
SM_ADMIN_NAME | Administrator | Display name. |
SM_PORT | 8090 | Port the panel listens on (host networking). |
SM_BIND | 0.0.0.0 | Listen address. Set to 127.0.0.1 once the panel domain works, so it's only reachable over HTTPS. |
SM_PANEL_DOMAIN_PORT | 2509 | Port the panel domain is served on, e.g. https://panel.example.com:2509. Must differ from SM_PORT. The panel is never served on 80/443 for that domain, so you can gate it with a firewall rule. Set to 443 to use the standard HTTPS port instead. |
SM_INSTALL_DIR | /opt/server-manager | Host path of the git checkout. Used by Settings → Update now. |
SM_HOME_PATH | /home | File manager jail, and parent of the deploy user's home. |
SM_DEPLOY_USER | deploy | Linux user that owns projects and runs PHP-FPM, workers and cron. |
SM_PHP_VERSIONS | 8.3,8.4 | Fallback list if PHP detection on the host fails. |
SM_MYSQL_HOST / _PORT | 127.0.0.1 / 3306 | Host MySQL server. |
SM_MYSQL_USER / _PASSWORD | sm_admin / — | Admin account used to create databases and users (created by the provision script). |
SM_CERTBOT_EMAIL | — | Default Let's Encrypt contact (can be changed in Settings). |
APP_KEY | auto | Laravel encryption key. Encrypts stored DB passwords, webhook secrets and 2FA secrets. Left empty, one is generated into the data volume on first boot. Don't change it once data exists. |
APP_URL | — | Public panel URL. Update it when you add a panel domain. Webhook URLs are built from the address you're browsing the panel on, so open it via the domain before copying one. |
APP_TIMEZONE | UTC | Timezone for the UI's cron previews (match the server's). |
SESSION_SECURE_COOKIE | false | Set to true once you only use HTTPS. |
SESSION_LIFETIME | 240 | Minutes before an idle session expires. |
Panel domain & HTTPS
Out of the box the panel is served over plain HTTP on http://IP:8090. To put it on its own domain with a certificate:
- Point DNS
Create an A record, e.g.
panel.example.com → your droplet IP. - Settings → Panel domain
Enter the domain and keep "Issue SSL certificate" on. The panel writes a host nginx vhost on
SM_PANEL_DOMAIN_PORT(default2509) that reverse-proxies to127.0.0.1:8090, opens that port in UFW and requests a certificate. Port 80 only answers Let's Encrypt challenges for the domain (it must stay open for issuing and renewing), and port 443 refuses the connection, sohttps://panel.example.comwithout the port loads nothing. -
Lock it down
Once
https://panel.example.com:2509works, edit.env:SM_BIND=127.0.0.1 SESSION_SECURE_COOKIE=true APP_URL=https://panel.example.com:2509Then apply it and close the old raw port in UFW:
$ docker compose up -d $ ufw delete allow 8090/tcpFinally, allow the panel port only from your own IPs in your network firewall (e.g. a DigitalOcean Cloud Firewall).
Only bind to 127.0.0.1 after you've confirmed the domain loads. If you lock yourself out, SSH in, set SM_BIND=0.0.0.0 and run docker compose up -d.
Changing the panel domain port
Use the script rather than editing .env by hand. It updates SM_PANEL_DOMAIN_PORT (and APP_URL if it uses the old port), recreates the container, rewrites the panel's nginx vhost, opens the new port in UFW and closes the old one. If nginx rejects the new port, everything is put back.
$ cd /opt/server-manager
$ sudo bash scripts/panel-port.sh 2509
Run it without a port to re-apply the one already in .env, e.g. after editing it by hand. Afterwards, open the new port in your network firewall and close the old one.