Deploying a Bottle app on a virtual private server (VPS) makes it available over the internet without running the development server on your own computer. You’ll install Python and the app’s dependencies, run Bottle behind a production WSGI server, and put Nginx in front to handle web traffic. You’ll need a Linux VPS, SSH access, and a domain name if you want to use one.
What You’ll Need
- A VPS running a supported Linux distribution, such as Ubuntu or Debian, with an account that can use sudo.
- SSH access to the server and your app’s source code, either in a Git repository or copied from your computer.
- A domain name, optional for testing but needed for a convenient public hostname and HTTPS certificate.
- Basic familiarity with the terminal and your app’s startup requirements, including any environment variables.
Step-by-Step
- Connect and update the server. From your computer, connect with
ssh username@SERVER_IP, substituting your account and server address. Update packages withsudo apt updateandsudo apt upgrade. Commands below use the Debian/Ubuntu package manager; other distributions use different package commands. Create a non-root user with sudo privileges if you only have a root login, and use that account for routine work. - Install Python tools and Nginx. Run
sudo apt install python3 python3-venv python3-pip nginx git. Confirm Python is available withpython3 --version. If your app uses a database, install or configure its client libraries and service separately according to the app’s requirements. - Put the application on the server. Choose a directory for the app, for example
/var/www/bottle-app. You can clone a repository into a user-owned directory, or copy files using a secure transfer method. Avoid placing secrets such as API keys in a public repository. Check that the app’s entry-point file and dependency file, commonlyrequirements.txt, are present. - Create an isolated environment and install dependencies. From the app directory, run
python3 -m venv .venv, then. .venv/bin/activate. Install the declared packages withpython -m pip install --upgrade pipandpip install -r requirements.txt. Add Bottle and a production WSGI server such as Waitress to the requirements if the project does not already list them. Do not rely on packages installed globally for another application. - Make the app expose a WSGI application. Bottle apps can be run through a WSGI server without using Bottle’s built-in development server. For example, if
app.pydefinesapp = Bottle(), Waitress can load it asapp:app. Test the import from the project directory using.venv/bin/python -c "from app import app; print(app)". Adjust the module and variable names to match your project. Fix import errors before configuring the service. - Test locally on the VPS. Start Waitress temporarily with
.venv/bin/waitress-serve --host=127.0.0.1 --port=8000 app:app. In a second SSH session, runcurl -i http://127.0.0.1:8000/. Confirm that the expected route responds. Stop the temporary process with Ctrl+C. Binding to the loopback address keeps this test server inaccessible directly from the public network. - Run the app with systemd. Create a service file using
sudo nano /etc/systemd/system/bottle-app.service. A basic configuration is:[Unit]
Description=Bottle web application
After=network.target[Service]
User=YOUR_USER
WorkingDirectory=/var/www/bottle-app
EnvironmentFile=-/etc/bottle-app.env
ExecStart=/var/www/bottle-app/.venv/bin/waitress-serve --host=127.0.0.1 --port=8000 app:app
Restart=on-failure[Install]
WantedBy=multi-user.target
ReplaceYOUR_USER, the directory, and the WSGI target as needed. Create the optional environment file with restricted permissions if the app needs secrets; do not put secret values in a world-readable file. Then runsudo systemctl daemon-reload,sudo systemctl enable --now bottle-app, andsudo systemctl status bottle-app. - Configure Nginx as a reverse proxy. Create an Nginx site configuration that listens on port 80 and forwards requests to Waitress. Inside the server block, include
server_name example.com www.example.com;and a location block withproxy_pass http://127.0.0.1:8000;,proxy_set_header Host $host;,proxy_set_header X-Real-IP $remote_addr;, andproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;. Replace the example hostname. Enable the site using the distribution’s Nginx configuration layout, check it withsudo nginx -t, then apply it withsudo systemctl reload nginx. Keep the app port private; do not open port 8000 to the internet. - Point your domain and enable HTTPS. Set the domain’s DNS records to the VPS address and wait for them to resolve. Allow inbound web traffic in the VPS firewall and any provider firewall. Once the hostname reaches Nginx, install Certbot using the current instructions for your distribution and Nginx, then request a certificate for the hostname. Verify HTTPS and certificate renewal rather than assuming DNS or certificate setup succeeded.
- Check the deployment and plan updates. Visit the site over HTTPS and test important routes, forms, and static files. Review
sudo journalctl -u bottle-app -n 100 --no-pagerand the Nginx error log if something fails. For each update, deploy the changed code, install any dependency changes in the virtual environment, and restart withsudo systemctl restart bottle-app. Keep a known-good revision so you can roll back.
Common Mistakes
- Using Bottle’s development server in production: it is intended for development, not as the public-facing deployment service. Use a production WSGI server behind Nginx.
- Binding the app to a public interface: keep the WSGI server on
127.0.0.1when Nginx is on the same VPS. Exposing its port can bypass the proxy and its settings. - Using the wrong working directory or WSGI target: systemd must run where imports work, and
module:variablemust identify the actual Bottle application. - Putting secrets in code or weakly protected files: restrict access to environment files and never commit credentials to source control.
- Forgetting to reload after configuration changes: test Nginx configuration before reloading, and reload systemd after editing a service file.
Tips
- Keep the app, virtual environment, and service account permissions consistent; the service user must be able to read code and write only to directories the app actually needs.
- Use environment variables for deployment-specific settings, and make the app log useful errors to standard output or standard error so systemd can capture them.
- For larger deployments, add monitoring, backups for persistent data, and a repeatable deployment process. A VPS restart should not erase important user uploads or database contents.
- Set Bottle’s proxy handling appropriately when the app needs accurate scheme or client-address information behind Nginx; trust forwarded headers only from your proxy.
Troubleshooting
If the site returns a gateway error, check sudo systemctl status bottle-app and the service journal first. A crashed process, wrong WSGI target, missing package, or port mismatch commonly prevents Nginx from reaching the app. Run the local curl test again and ensure Nginx’s upstream address and port match the Waitress command.
If the app works locally but not through the domain, check that DNS points to the correct server, Nginx recognizes the hostname, and ports 80 and 443 are allowed by both the operating-system and provider firewalls. Use sudo nginx -t to identify syntax errors. If HTTPS issuance fails, confirm DNS has propagated and that the hostname can reach the server over HTTP before retrying.
For import or permission errors, inspect the service’s WorkingDirectory, virtual-environment paths, and file ownership. Test the import using the same Python environment used by systemd. For a blank or incorrect page, inspect the application logs and test the exact route directly with curl.
Frequently Asked Questions
Can I deploy Bottle without Nginx?
Yes, a WSGI server can serve the app, but Nginx is commonly used as a reverse proxy for public HTTP traffic, TLS termination, and static files.
Do I need a domain name?
No. You can test using the VPS IP address, but a domain is more convenient and is normally needed for a standard HTTPS certificate setup.
Why use Waitress instead of Bottle’s built-in server?
Bottle’s built-in server is intended for development. Waitress is a separate WSGI server suitable for running the application as a managed service.
How do I make code changes live?
Deploy the updated files, install changed dependencies in the virtual environment, then restart the systemd service. Confirm the service is active and test the affected routes.
Where can I find error messages?
Use sudo journalctl -u bottle-app for application service output and check Nginx’s error log for proxy or configuration problems.
Related
General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.
More in this bed
- How to Use an iMessage Group Chat
- Record Video From Your iPhone on a Mac
- How to Copy Text from a Video on iPhone
- Epson XP-330 Driver Issues: How to Fix Them
- Import Data From the Web Into Microsoft Excel
- How to Transfer Music to iPhone 15