This guide covers deploying CoolSolve GUI on an Ubuntu 24.04 server behind Apache as a reverse proxy, with user authentication, automatic startup, and proper security.
Internet → Apache (port 443/80) → reverse proxy → CoolSolve (localhost:8550)
Apache handles TLS, authentication, and public access. CoolSolve listens only on 127.0.0.1:8550 and is not directly exposed to the internet.
# Update system
sudo apt update && sudo apt upgrade -y
# Install Apache and required modules
sudo apt install -y apache2 apache2-utils
# Enable required Apache modules
sudo a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl auth_basic
sudo systemctl restart apache2CoolSolve is assumed to be already compiled at /home/coolsolve/CoolSolve/build/coolsolve.
If not already done, create a dedicated system user for CoolSolve (no login shell, no home directory login):
# If the 'coolsolve' user doesn't exist yet:
sudo useradd -r -s /usr/sbin/nologin -d /home/coolsolve -m coolsolve
# Ensure ownership of the CoolSolve installation
sudo chown -R coolsolve:coolsolve /home/coolsolve/CoolSolveIf the user already exists with a normal shell, you can restrict it:
sudo usermod -s /usr/sbin/nologin coolsolve# Set restrictive permissions on the installation directory
sudo chmod 750 /home/coolsolve/CoolSolve
sudo chmod 750 /home/coolsolve/CoolSolve/build
# The coolsolve binary must be executable
sudo chmod 755 /home/coolsolve/CoolSolve/build/coolsolve
# Examples directory must be readable by the coolsolve user
sudo chmod -R 755 /home/coolsolve/CoolSolve/examples
# Create a writable temp directory for session data
sudo mkdir -p /tmp/coolsolve_sessions
sudo chown coolsolve:coolsolve /tmp/coolsolve_sessions
sudo chmod 700 /tmp/coolsolve_sessionsCreate the service file:
sudo tee /etc/systemd/system/coolsolve.service > /dev/null << 'EOF'
[Unit]
Description=CoolSolve GUI Server
After=network.target
[Service]
Type=simple
User=coolsolve
Group=coolsolve
WorkingDirectory=/home/coolsolve/CoolSolve/build
ExecStart=/home/coolsolve/CoolSolve/build/coolsolve --gui 8550 --no-browser
Restart=on-failure
RestartSec=5
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/tmp/coolsolve_sessions
PrivateTmp=false
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictSUIDSGID=true
# Environment
Environment=HOME=/home/coolsolve
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=coolsolve
[Install]
WantedBy=multi-user.target
EOFEnable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable coolsolve
sudo systemctl start coolsolve
# Verify it's running
sudo systemctl status coolsolve
journalctl -u coolsolve -f # follow logsUseful commands:
sudo systemctl restart coolsolve # restart after recompilation
sudo systemctl stop coolsolve # stop the server
journalctl -u coolsolve --since today # today's logssudo tee /etc/apache2/sites-available/coolsolve.conf > /dev/null << 'EOF'
<VirtualHost *:80>
ServerName coolsolve.example.com
# --- Authentication ---
<Location />
AuthType Basic
AuthName "CoolSolve"
AuthUserFile /etc/apache2/.htpasswd-coolsolve
Require valid-user
</Location>
# --- Reverse Proxy ---
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8550/
ProxyPassReverse / http://127.0.0.1:8550/
# --- SSE support (Server-Sent Events for solve progress) ---
# Disable buffering for the streaming endpoint
<Location /api/v1/solve/stream>
ProxyPass http://127.0.0.1:8550/api/v1/solve/stream
ProxyPassReverse http://127.0.0.1:8550/api/v1/solve/stream
# Disable proxy buffering for SSE
SetEnv proxy-sendchunked 1
SetEnv proxy-interim-response RFC
</Location>
# --- Security Headers ---
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# --- Logging ---
ErrorLog ${APACHE_LOG_DIR}/coolsolve_error.log
CustomLog ${APACHE_LOG_DIR}/coolsolve_access.log combined
</VirtualHost>
EOFInstall Certbot:
sudo apt install -y certbot python3-certbot-apacheCreate the HTTPS site config:
sudo tee /etc/apache2/sites-available/coolsolve-ssl.conf > /dev/null << 'EOF'
<VirtualHost *:80>
ServerName coolsolve.example.com
# Redirect all HTTP to HTTPS
RewriteEngine On
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
<VirtualHost *:443>
ServerName coolsolve.example.com
# --- SSL ---
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/coolsolve.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/coolsolve.example.com/privkey.pem
# --- Authentication ---
<Location />
AuthType Basic
AuthName "CoolSolve"
AuthUserFile /etc/apache2/.htpasswd-coolsolve
Require valid-user
</Location>
# --- Reverse Proxy ---
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8550/
ProxyPassReverse / http://127.0.0.1:8550/
# --- SSE support ---
<Location /api/v1/solve/stream>
ProxyPass http://127.0.0.1:8550/api/v1/solve/stream
ProxyPassReverse http://127.0.0.1:8550/api/v1/solve/stream
SetEnv proxy-sendchunked 1
SetEnv proxy-interim-response RFC
</Location>
# --- Security Headers ---
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "DENY"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
# --- Logging ---
ErrorLog ${APACHE_LOG_DIR}/coolsolve_error.log
CustomLog ${APACHE_LOG_DIR}/coolsolve_access.log combined
</VirtualHost>
EOFObtain the certificate and enable:
# Temporarily enable plain HTTP site for Certbot challenge
sudo a2ensite coolsolve.conf
sudo systemctl reload apache2
# Obtain certificate
sudo certbot certonly --apache -d coolsolve.example.com
# Disable plain HTTP, enable SSL site
sudo a2dissite coolsolve.conf
sudo a2ensite coolsolve-ssl.conf
sudo systemctl reload apache2Note: Replace
coolsolve.example.comwith your actual domain name throughout.
# Create the file and add the first user (will prompt for password)
sudo htpasswd -c /etc/apache2/.htpasswd-coolsolve admin
# Add additional users (without -c, to avoid overwriting)
sudo htpasswd /etc/apache2/.htpasswd-coolsolve alice
sudo htpasswd /etc/apache2/.htpasswd-coolsolve bob
# Secure the password file
sudo chown root:www-data /etc/apache2/.htpasswd-coolsolve
sudo chmod 640 /etc/apache2/.htpasswd-coolsolve# Change a user's password
sudo htpasswd /etc/apache2/.htpasswd-coolsolve alice
# Remove a user
sudo htpasswd -D /etc/apache2/.htpasswd-coolsolve bob
# List users
cut -d: -f1 /etc/apache2/.htpasswd-coolsolveImportant: Basic Auth sends credentials in base64 (not encrypted). Always use HTTPS in production to protect passwords in transit.
# Enable the site
sudo a2ensite coolsolve.conf # or coolsolve-ssl.conf for HTTPS
# Disable the default site if not needed
# sudo a2dissite 000-default.conf
# Test Apache configuration
sudo apache2ctl configtest
# Reload Apache
sudo systemctl reload apache2Verify everything works:
# Check CoolSolve is listening
curl -s http://127.0.0.1:8550/api/v1/health
# Expected: {"coolpropReady":true,"status":"ok"}
# Check Apache proxy (with auth)
curl -s -u admin:yourpassword http://coolsolve.example.com/api/v1/health# Allow HTTP and HTTPS through the firewall
sudo ufw allow 'Apache Full'
# Ensure CoolSolve port is NOT exposed externally (it should only be on 127.0.0.1)
# Verify:
sudo ss -tlnp | grep 8550
# Should show: 127.0.0.1:8550 or 0.0.0.0:8550If CoolSolve binds to 0.0.0.0:8550 (it does by default), block external access to that port:
sudo ufw deny 8550Note: A future improvement would be to make CoolSolve bind to
127.0.0.1only (via a--bindflag). For now, the firewall rule above prevents external access.
After recompiling CoolSolve (e.g., after a git pull or svn update):
cd /home/coolsolve/CoolSolve/build
sudo -u coolsolve cmake ..
sudo -u coolsolve make -j$(nproc) coolsolve
# Restart the service to load the new binary
sudo systemctl restart coolsolve
# Verify
sudo systemctl status coolsolveIf the frontend was also rebuilt:
cd /home/coolsolve/CoolSolve/gui
sudo -u coolsolve npm run build
cd /home/coolsolve/CoolSolve/build
sudo -u coolsolve cmake .. # re-embed assets
sudo -u coolsolve make -j$(nproc) coolsolve
sudo systemctl restart coolsolveIf CoolSolve should be available at https://yourserver.com/coolsolve/ instead of root, the Apache config needs path rewriting. This requires CoolSolve API calls to be aware of the prefix; the current embedded SPA uses relative paths so this should work:
<Location /coolsolve/>
AuthType Basic
AuthName "CoolSolve"
AuthUserFile /etc/apache2/.htpasswd-coolsolve
Require valid-user
ProxyPass http://127.0.0.1:8550/
ProxyPassReverse http://127.0.0.1:8550/
</Location># CoolSolve application logs
journalctl -u coolsolve -f
# Apache access/error logs
tail -f /var/log/apache2/coolsolve_access.log
tail -f /var/log/apache2/coolsolve_error.logApache logs are rotated automatically by logrotate (installed by default on Ubuntu). CoolSolve logs go through journald, which handles its own retention. To configure journald retention:
sudo tee -a /etc/systemd/journald.conf > /dev/null << 'EOF'
SystemMaxUse=500M
MaxRetentionSec=30day
EOF
sudo systemctl restart systemd-journald| Symptom | Check |
|---|---|
| 502 Bad Gateway | sudo systemctl status coolsolve — is it running? |
| 403 Forbidden | Check .htpasswd file permissions and Apache auth config |
| SSE/progress not streaming | Verify proxy-sendchunked env is set in Apache config |
| Slow CoolProp startup | First request after restart triggers warmup (~1-2 s); this is normal |
| Session lost between requests | Ensure Apache forwards cookies (ProxyPreserveHost On) |
| Permission denied in logs | Check that coolsolve user owns the working directory |
Check all components:
# 1. Is CoolSolve running?
sudo systemctl status coolsolve
# 2. Can it be reached locally?
curl -s http://127.0.0.1:8550/api/v1/health
# 3. Is Apache running?
sudo systemctl status apache2
# 4. Apache config valid?
sudo apache2ctl configtest
# 5. Firewall rules
sudo ufw status verbose| Component | Location |
|---|---|
| CoolSolve binary | /home/coolsolve/CoolSolve/build/coolsolve |
| Systemd service | /etc/systemd/system/coolsolve.service |
| Apache site config | /etc/apache2/sites-available/coolsolve.conf |
| Password file | /etc/apache2/.htpasswd-coolsolve |
| Application logs | journalctl -u coolsolve |
| Apache logs | /var/log/apache2/coolsolve_{access,error}.log |
| Session temp data | /tmp/coolsolve_sessions/ |
| Examples | /home/coolsolve/CoolSolve/examples/ |