A portable deployment script for containerized applications on VPS servers. This script automates the setup of your application with Nginx reverse proxy, SSL certificates, and container orchestration.
- ✅ Podman & podman-compose: Rootless container orchestration
- ✅ SSL Certificates: Automatic Let's Encrypt SSL setup with auto-renewal
- ✅ Nginx Reverse Proxy: Pre-configured with rate limiting and streaming support
- ✅ Swap Space: Automatic swap configuration for memory management
- ✅ Framework Agnostic: Works with any app that has Dockerfile and compose.yml
- ✅ Environment Management: Easy .env file configuration
- Ubuntu/Debian-based system (tested on Ubuntu 20.04+)
- Root or sudo access
- DNS A record pointing your domain to the VPS IP
Your application must include:
Dockerfile- Container build instructionsdocker-compose.ymlorcompose.yml- Service orchestration
Example compose.yml structure:
services:
web:
build: .
ports:
- "3000:3000" # Make sure this matches APP_PORT in config
environment:
- NODE_ENV=production
# ... other services like databases-
Download the deployment script
wget https://raw.githubusercontent.com/HMZElidrissi/self-host-vps/main/deploy.sh wget https://raw.githubusercontent.com/HMZElidrissi/self-host-vps/main/config.example.sh chmod +x deploy.sh
-
Create your configuration
cp config.example.sh config.sh nano config.sh # Edit with your settings -
Run the deployment
./deploy.sh
Edit config.sh with your application details:
# Your git repository
REPO_URL="https://github.com/HMZElidrissi/super-cool-app"
# Application name (used for directories and configs)
APP_NAME="super-cool-app"
# Your domain name
DOMAIN_NAME="super-cool-app.com"
# Email for SSL certificates
EMAIL="[email protected]"
# Port your app runs on (must match your compose file)
APP_PORT="3000"# Swap space size (default: 2G)
SWAP_SIZE="2G"
# Custom application directory (default: ~/$APP_NAME)
APP_DIR="/opt/myapp"The ENV_VARS section in config.sh will be written to .env in your application directory:
ENV_VARS="
DATABASE_URL=postgres://user:password@db:5432/myapp
NODE_ENV=production
API_KEY=your-secret-key
"Important: Keep sensitive data in config.sh and never commit it to version control!
-
System Setup
- Updates system packages
- Configures swap space
- Installs Podman and podman-compose
-
Application Deployment
- Clones/updates your git repository
- Creates .env file from configuration
- Builds container images with Podman
- Starts all services
-
Web Server Configuration
- Installs and configures Nginx
- Obtains SSL certificate from Let's Encrypt
- Sets up reverse proxy with:
- HTTPS redirect
- Rate limiting (10 req/sec)
- WebSocket support
- Streaming support
-
SSL Auto-Renewal
- Configures cron job to renew certificates every 12 hours
After successful deployment, your application will be available at https://super-cool-app.com
Navigate to your app directory first:
cd ~/super-cool-app # or your custom APP_DIRView logs:
podman-compose logs -fRestart services:
podman-compose restartStop services:
podman-compose downRebuild and restart:
podman-compose up -d --buildUpdate application:
git pull
podman-compose up -d --buildcd ~/super-cool-app
podman-compose logs- Ensure DNS is properly configured before running script
- Check that port 80 is not blocked by firewall
- Verify email address is valid
sudo nginx -t # Test configuration
sudo systemctl status nginx # Check service status
sudo tail -f /var/log/nginx/error.log # View error logs- Ensure APP_PORT in config matches your compose.yml
- Check no other service is using the same port:
sudo netstat -tlnp | grep :3000- Keep config.sh private - It may contain sensitive information
- Use strong passwords - For databases and services
- Review firewall rules - Only expose necessary ports:
sudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw allow 22/tcp sudo ufw enable - Regular updates - Keep your system and containers updated
The script creates an Nginx config at /etc/nginx/sites-available/$APP_NAME. You can customize it after deployment:
sudo nano /etc/nginx/sites-available/myapp
sudo nginx -t
sudo systemctl reload nginxYou can run the script multiple times with different configurations for multiple applications on the same VPS. Just use different:
- APP_NAME
- DOMAIN_NAME
- APP_PORT