Deployment

Guidelines for running js-cgi in production.

Recommended Directory Structure

/var/www/myapp/
├── index.js              # Entry point
├── includes/             # Shared templates
│   ├── header.js
│   └── footer.js
├── modules/              # ES modules (libraries)
│   ├── db.js
│   └── auth.js
├── api/                  # API endpoints
│   ├── users.js
│   └── posts.js
├── static/               # CSS, images, client JS
│   ├── style.css
│   └── logo.png
└── data/                 # SQLite databases, uploads
    └── app.db

Apache Virtual Host

<VirtualHost *:80>
    ServerName myapp.com
    DocumentRoot /var/www/myapp
    DirectoryIndex index.js

    Action js-cgi /cgi-bin/js-cgi
    AddHandler js-cgi .js

    ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/

    # Serve static files directly (bypass js-cgi)
    Alias /static /var/www/myapp/static
    <Directory /var/www/myapp/static>
        Require all granted
        # Cache static assets
        ExpiresActive On
        ExpiresByType text/css "access plus 1 week"
        ExpiresByType image/png "access plus 1 month"
        ExpiresByType image/jpeg "access plus 1 month"
    </Directory>

    <Directory /var/www/myapp>
        Options +ExecCGI
        AllowOverride All
        Require all granted
    </Directory>

    <Directory /usr/lib/cgi-bin>
        Require all granted
    </Directory>

    # Block direct access to data directory
    <Directory /var/www/myapp/data>
        Require all denied
    </Directory>

    # Custom error pages
    ErrorDocument 404 /404.js
    ErrorDocument 500 /500.js
</VirtualHost>

HTTPS with Let's Encrypt

sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d myapp.com

Log Rotation

Create /etc/logrotate.d/js-cgi:

/var/log/js-cgi/error.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
    create 640 www-data www-data
}

Production INI

memory_limit = 64M
max_execution_time = 15
display_errors = Off
error_log = /var/log/js-cgi/error.log
extension_dir = /usr/lib/js-cgi/modules
extension = sqlite.so
extension = session.so
extension = file.so
extension = crypto.so
extension = http.so

File Permissions

# Application files (read-only for web server)
sudo chown -R root:www-data /var/www/myapp
sudo chmod -R 750 /var/www/myapp
sudo chmod -R 644 /var/www/myapp/*.js /var/www/myapp/**/*.js

# Data directory (writable)
sudo chown -R www-data:www-data /var/www/myapp/data
sudo chmod 750 /var/www/myapp/data

# Log directory
sudo mkdir -p /var/log/js-cgi
sudo chown www-data:www-data /var/log/js-cgi

Monitoring

Monitor your application by checking:

  • /var/log/js-cgi/error.log for application errors
  • /var/log/apache2/error.log for server errors
  • /var/log/apache2/access.log for request patterns
# Watch for errors in real-time
tail -f /var/log/js-cgi/error.log

# Count errors in the last hour
grep "$(date +%Y-%m-%d)" /var/log/js-cgi/error.log | wc -l

Backup

Back up your SQLite databases regularly:

# Add to crontab
0 * * * * sqlite3 /var/www/myapp/data/app.db ".backup /var/backups/app-$(date +\%Y\%m\%d-\%H).db"
Was this page helpful?