Server Setup Guide¶
This guide explains how to set up Hop3 on a server using the installer script. The installer is a standalone Python script that automates the installation and configuration process.
Prerequisites¶
- A server running Ubuntu 24.04 or 26.04 LTS (Debian-based distributions also supported)
- Root access to the server via SSH
- Python 3.10+ on the server
- A domain name pointing to your server (required for secure HTTPS; without it, admin UI uses unencrypted HTTP on port 8000)
Quick Install¶
One-liner (from PyPI)¶
With Admin Domain (Recommended)¶
For secure HTTPS access to the admin UI, specify a domain:
This will:
- Configure nginx to serve the admin UI at https://hop3.example.com/
- Request a Let's Encrypt SSL certificate automatically
- Store the admin domain in the server configuration
Installation Options¶
From Git (Development)¶
Install from a specific git branch:
From Local Path¶
For development or testing with local code:
All Options¶
| Option | Description |
|---|---|
--domain DOMAIN |
Domain for admin UI (enables Let's Encrypt SSL) |
--acme-email EMAIL |
Email for Let's Encrypt registration (required when using --domain) |
--with FEATURES |
Comma-separated optional features: mysql, redis, docker, nix, s3, or all |
--version VERSION |
Install specific version from PyPI |
--pre |
Allow pre-release versions from PyPI |
--from git |
Install from git repository |
--branch BRANCH |
Git branch to install (default: main) |
--path PATH |
Install from local directory |
--force |
Force reinstall |
--skip-deps |
Skip system dependency installation |
--skip-nginx |
Skip nginx configuration |
--skip-postgres |
Skip PostgreSQL setup |
--skip-acme |
Skip ACME/Let's Encrypt setup |
--verbose |
Show detailed output |
What the Installer Does¶
- System Dependencies: Installs required packages (nginx, PostgreSQL, Python dev tools, etc.)
- User Setup: Creates
hop3user and group - Virtual Environment: Creates Python venv at
/home/hop3/venv - Package Installation: Installs hop3-server
- Initial Setup: Runs
hop3-server setupto create directories and config - SSH Keys: Copies root's SSH keys to hop3 user
- Systemd Services: Configures hop3-server and uwsgi-hop3 services
- SSL Certificates: Generates self-signed cert (or Let's Encrypt if domain provided)
- Nginx: Configures reverse proxy for the admin UI and API
- PostgreSQL: Creates hop3 database and user, configures for Docker access
- Server Config: Writes
/home/hop3/hop3-server.tomlwith settings
Admin UI Access¶
With Domain (Recommended)¶
When you install with --domain hop3.example.com:
- Admin UI:
https://hop3.example.com/ - API (RPC):
https://hop3.example.com/rpc - SSL: Let's Encrypt certificate (auto-renewed)
Deployed applications use their own hostnames (e.g., myapp.example.com).
Without Domain¶
Without --domain, the admin UI is only accessible directly on port 8000:
- Admin UI:
http://<server-ip>:8000/(unsecured) - API (RPC):
https://<server-ip>/rpc(self-signed cert)
Warning: Port 8000 access is unencrypted. Use
--domainfor production deployments.
For development/testing, you can use SSH tunneling:
Post-Installation Steps¶
Sign In¶
The installer does not create an admin user or print a token; the first hop3 login does it for you.
From your own machine:
SSH access to the server is administrator access (ADR 014), so there is no password to type. This runs admin:ssh-token on the server, auto-creating a default admin if none exists, and stores the token in ~/.config/hop3-cli/credentials.toml.
That signs in the CLI and records the server's own HTTPS address when it has an admin domain. SSH is the bootstrap, not the everyday route: the Web UI holds a separate credential, and hop3 login --browser prints a one-time link for it (over SSH as well), good for 5 minutes and one use.
To do the same on the server itself, run hop3-server as the hop3 user so the database stays owned by hop3 and not by root:
ssh root@your-server.com
sudo -u hop3 /home/hop3/venv/bin/hop3-server admin:create admin admin@example.com
sudo -u hop3 /home/hop3/venv/bin/hop3-server admin:token admin
sudo -u hop3 /home/hop3/venv/bin/hop3-server admin:reset-password admin
sudo -u hop3 /home/hop3/venv/bin/hop3-server auth:magic-link admin
sudo -u hop3 /home/hop3/venv/bin/hop3-server admin:list
Then sign the local CLI in with a token you printed that way:
Signing In covers the whole picture: which credential each surface holds, why the Web UI needs HTTPS, how to name several servers, and what to do when you cannot get in.
For Automation (CI/CD)¶
Use non-interactive mode:
echo "$ADMIN_PASSWORD" | hop3 init \
--ssh deploy@my-server.com \
--username admin \
--email admin@company.com \
--url https://my-server.com \
--password-stdin \
--yes
Using the Demo Launcher¶
For testing and demonstrations, use the demo launcher:
# Basic demo (apps cleaned up after)
python demos/demo.py run --host <your-server-ip> demo01
# Keep apps running with admin domain
python demos/demo.py run --host <your-server-ip> --admin-domain hop3.example.com --keep demo01
# Use local code (development)
python demos/demo.py run --host <your-server-ip> --local --keep demo01
The demo launcher will: - Install/update Hop3 on the target server - Configure the admin domain (if specified) - Create an admin user - Deploy demo applications - Show admin credentials and UI URL at the end
Verification¶
After installation, verify services are running:
Check logs:
Troubleshooting¶
Services Not Starting¶
Check service status and logs:
SSL Certificate Issues¶
For Let's Encrypt, ensure: - Domain DNS points to your server's IP - Ports 80 and 443 are open - No other service is using port 80
To manually request a certificate:
PostgreSQL Connection Issues¶
Verify PostgreSQL is configured for the hop3 user:
Admin UI Shows 404¶
If using a domain and getting 404:
1. Verify nginx config: sudo nginx -t
2. Check nginx is proxying to hop3-server: cat /etc/nginx/sites-available/hop3
3. Ensure hop3-server is running on port 8000
Bare Host Serves the Wrong App (or the Default Nginx Page)¶
Symptom: http://your-server/ shows the default nginx welcome page, or
https://your-server/ shows one of your deployed apps (with the wrong TLS
certificate) instead of the Hop3 Web UI.
Cause: the control plane isn't claiming the bare host. Each app's nginx
vhost matches only its own server_name, so a request to a host that matches no
app falls through to whichever vhost nginx loaded first (the distro default on
port 80, an arbitrary app on port 443). This happens on servers installed before
the control plane started pinning nginx's default_server.
Fix: redeploy. hop3-deploy-server --host your-server.com now makes
your-server.com the admin hostname automatically and pins the Hop3 control
plane as nginx's default_server, so the bare host and any unmatched Host
reach the Web UI instead of a random app. To serve the Web UI on a different
hostname, pass it explicitly:
# Developer tool with a different admin hostname:
hop3-deploy-server --from local --host your-server.com --admin-domain admin.your-server.com
# Production installer (uses --domain):
curl -LsSf https://hop3.cloud/install-server.py | sudo python3 - --domain your-server.com
The admin-domain step runs on every deploy, so a redeploy re-asserts the control-plane vhost and self-heals an older box (no
--cleanrequired). (On RHEL/Fedora thedefault_serverpin is skipped to avoid clashing with the stocknginx.conf; theserver_namematch still routes the admin host.)
Support¶
For additional help or to report issues: - GitHub: https://github.com/abilian/hop3/issues - Documentation: https://hop3.cloud/