Self-Hosting Guide
Host Calcora on your own server with full control over deployment, privacy, and customization.
Overview
Calcora can be self-hosted for maximum privacy, control, and customization. Perfect for:
- 🏫 Educational institutions wanting private infrastructure
- 🔒 Privacy-conscious users who want full data control
- ⚙️ Developers integrating Calcora into their systems
- 🌐 Organizations with airgapped or restricted networks
pip install calcora && calcora serve
Method 1: Python Package (Recommended)
The easiest way to self-host Calcora. Requires Python 3.10 or later.
Installation
# Install Calcora with API server dependencies
pip install calcora[api]
# Or install from GitHub (latest development version)
pip install git+https://github.com/Dumbo-programmer/Calcora.git
Running the Server
# Start the API server (defaults to port 5000)
calcora serve
# Specify custom port and host
calcora serve --port 8080 --host 0.0.0.0
# Production mode with Gunicorn (recommended)
pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:5000 api_server:app
Environment Variables
| Variable | Default | Description |
|---|---|---|
CALCORA_STATIC_FOLDER |
src/calcora/web |
Path to static web files |
FLASK_ENV |
production |
Flask environment mode |
CALCORA_MAX_TIMEOUT |
10 |
Maximum computation timeout (seconds) |
Example: Production Setup
# Create a systemd service (Linux)
# Save as /etc/systemd/system/calcora.service
[Unit]
Description=Calcora API Server
After=network.target
[Service]
Type=simple
User=calcora
WorkingDirectory=/opt/calcora
Environment="FLASK_ENV=production"
Environment="CALCORA_STATIC_FOLDER=/opt/calcora/site"
ExecStart=/usr/bin/gunicorn -w 4 -b 127.0.0.1:5000 api_server:app
Restart=always
[Install]
WantedBy=multi-user.target
# Enable and start the service
sudo systemctl enable calcora
sudo systemctl start calcora
sudo systemctl status calcora
Method 2: Docker Deployment
Containerized deployment for consistent, isolated environments.
Create Dockerfile
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
# Install dependencies
COPY requirements-api.txt .
RUN pip install --no-cache-dir -r requirements-api.txt && \
pip install --no-cache-dir gunicorn
# Copy application
COPY api_server.py .
COPY src/ src/
COPY site/ site/
# Set environment variables
ENV FLASK_ENV=production
ENV CALCORA_STATIC_FOLDER=/app/site
# Expose port
EXPOSE 5000
# Run with Gunicorn
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "api_server:app"]
Build and Run
# Build the Docker image
docker build -t calcora:latest .
# Run the container
docker run -d -p 5000:5000 --name calcora-server calcora:latest
# Check logs
docker logs calcora-server
# Stop the container
docker stop calcora-server
Docker Compose
# docker-compose.yml
version: '3.8'
services:
calcora:
build: .
ports:
- "5000:5000"
environment:
- FLASK_ENV=production
- CALCORA_STATIC_FOLDER=/app/site
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/"]
interval: 30s
timeout: 10s
retries: 3
# Start with Docker Compose
docker-compose up -d
# View logs
docker-compose logs -f
# Stop
docker-compose down
Method 3: Running from Source
For development or when you need the latest features.
# Clone the repository
git clone https://github.com/Dumbo-programmer/Calcora.git
cd Calcora
# Create virtual environment
python -m venv .venv
.venv\Scripts\Activate.ps1 # Windows
source .venv/bin/activate # Linux/Mac
# Install dependencies
pip install -r requirements-api.txt
# Run the server
python api_server.py
For detailed build instructions, see the Build from Source Guide.
Reverse Proxy Configuration
Setup HTTPS and domain routing with nginx or Apache.
nginx Configuration
# /etc/nginx/sites-available/calcora
server {
listen 80;
server_name calcora.yourdomain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name calcora.yourdomain.com;
# SSL certificates (use Let's Encrypt: certbot --nginx)
ssl_certificate /etc/letsencrypt/live/calcora.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/calcora.yourdomain.com/privkey.pem;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Proxy to Calcora
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts for long computations
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Rate limiting (optional)
limit_req_zone $binary_remote_addr zone=calcora_limit:10m rate=10r/s;
limit_req zone=calcora_limit burst=20 nodelay;
}
# Enable the site
sudo ln -s /etc/nginx/sites-available/calcora /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Apache Configuration
# /etc/apache2/sites-available/calcora.conf
<VirtualHost *:80>
ServerName calcora.yourdomain.com
Redirect permanent / https://calcora.yourdomain.com/
</VirtualHost>
<VirtualHost *:443>
ServerName calcora.yourdomain.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/calcora.yourdomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/calcora.yourdomain.com/privkey.pem
# Security headers
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
# Proxy to Calcora
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
</VirtualHost>
# Enable required modules and site
sudo a2enmod ssl proxy proxy_http headers
sudo a2ensite calcora
sudo systemctl reload apache2
Security Considerations
🔒 Essential Security Measures
- HTTPS Required: Always use SSL/TLS in production (use Let's Encrypt for free certificates)
- Rate Limiting: Implement request rate limits to prevent abuse (shown in nginx config above)
- Firewall: Only expose necessary ports (443/80 for web, not 5000 directly)
- Updates: Keep Calcora and dependencies up to date with security patches
- Resource Limits: Configure computation timeouts to prevent resource exhaustion
Rate Limiting Configuration
# Using Flask-Limiter (install: pip install Flask-Limiter)
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
@app.route('/differentiate')
@limiter.limit("10 per minute")
def differentiate_get():
# ... existing code ...
Input Validation
Calcora includes built-in input validation and timeout protection:
- Expression parsing with syntax validation
- Timeout wrapper prevents infinite loops (default: 10 seconds)
- Safe evaluation using SymPy (no arbitrary code execution)
Performance Optimization
Production Server Configuration
# Gunicorn with 4 workers (adjust based on CPU cores)
gunicorn -w 4 \
--worker-class sync \
--timeout 60 \
--keep-alive 5 \
--max-requests 1000 \
--max-requests-jitter 100 \
-b 0.0.0.0:5000 \
api_server:app
Worker Count Formula
Recommended workers: (2 × CPU cores) + 1
# Auto-calculate workers
WORKERS=$(( $(nproc) * 2 + 1 ))
gunicorn -w $WORKERS -b 0.0.0.0:5000 api_server:app
- Use a reverse proxy (nginx/Apache) for static file serving
- Enable gzip compression for API responses
- Consider Redis caching for frequently requested computations
- Monitor resource usage with tools like
htopor Prometheus
Monitoring & Logging
Basic Logging Setup
# Configure Python logging in api_server.py
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('/var/log/calcora/api.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
Health Check Endpoint
Add a health check endpoint for monitoring:
@app.route('/health')
def health():
return jsonify({
'status': 'healthy',
'version': '0.2.0',
'timestamp': datetime.now().isoformat()
})
Monitoring Tools
- Uptime Monitoring: UptimeRobot, Pingdom, or StatusCake
- Application Monitoring: Prometheus + Grafana
- Log Aggregation: ELK Stack (Elasticsearch, Logstash, Kibana)
Troubleshooting
Server won't start
- Check if port 5000 is already in use:
netstat -tulpn | grep 5000 - Verify Python version:
python --version(requires 3.10+) - Check dependencies:
pip list | grep -E "flask|sympy|numpy"
502 Bad Gateway (nginx)
- Ensure Calcora is running:
systemctl status calcora - Check proxy_pass URL matches Calcora's host:port
- Verify firewall allows internal connections to port 5000
Slow computations / timeouts
- Increase timeout in nginx/Apache config (see
proxy_read_timeout) - Add more Gunicorn workers for parallel processing
- Check system resources:
htoportop
CORS errors in browser
- Verify Flask-CORS is installed:
pip show flask-cors - Check CORS configuration in api_server.py
- Ensure reverse proxy passes headers correctly
Cloud Deployment Options
Quick deployment on popular cloud platforms:
Render.com
# render.yaml (included in repository)
services:
- type: web
name: calcora
env: python
buildCommand: pip install -r requirements-api.txt
startCommand: gunicorn -w 4 -b 0.0.0.0:$PORT api_server:app
Deploy: Connect GitHub repo → Render auto-deploys on push
Railway.app
# railway.json
{
"build": {
"builder": "nixpacks"
},
"deploy": {
"startCommand": "gunicorn -w 4 -b 0.0.0.0:$PORT api_server:app"
}
}
DigitalOcean App Platform
Use the Dockerfile method shown above, or:
# .do/app.yaml
name: calcora
services:
- name: api
github:
repo: Dumbo-programmer/Calcora
branch: main
run_command: gunicorn -w 4 -b 0.0.0.0:8080 api_server:app
http_port: 8080
Need Help?
Self-hosting support resources:
- GitHub Issues — Report deployment issues or bugs
- GitHub Discussions — Ask questions about self-hosting
- Build from Source Guide — Building desktop or custom deployments
- API Documentation — API reference for custom integrations