Changes: - Fix Dockerfile COPY path from ../secrets to secrets/ (Docker doesn't allow parent directory access) - Create ssh-tunnel/secrets/ directory structure with comprehensive README - Add .dockerignore for ssh-tunnel to optimize build context - Add DOKPLOY_DEPLOYMENT.md with complete deployment guide including: * SSH key configuration options (repository, secrets manager, BuildKit) * Environment variables setup * Step-by-step deployment instructions * Troubleshooting section * Security best practices - Update .gitignore to allow secrets/README.md files for documentation This resolves the Dokploy build failure: "failed to calculate checksum of ref... /secrets/roa_oracle_server: not found" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
23 KiB
ROA2WEB Deployment Guide for Dokploy
This guide provides step-by-step instructions for deploying ROA2WEB to Dokploy, a modern Docker-based deployment platform.
Table of Contents
Prerequisites
Before deploying to Dokploy, ensure you have:
- ✅ A Dokploy instance running (cloud or self-hosted)
- ✅ Access to your Git repository (GitHub, GitLab, Gitea, etc.)
- ✅ SSH private key for Oracle database tunnel (
roa_oracle_server) - ✅ Oracle database credentials
- ✅ JWT secret key for authentication
- ✅ Telegram bot token (if using Telegram bot feature)
- ✅ Claude API key (if using Telegram bot with Claude SDK)
Quick Start
Option 1: Using Pre-Configured Secrets (Recommended)
-
Add SSH Key to Repository:
# In your local repository cp /path/to/your/roa_oracle_server ./ssh-tunnel/secrets/ chmod 600 ./ssh-tunnel/secrets/roa_oracle_server git add ssh-tunnel/secrets/roa_oracle_server git commit -m "Add SSH key for deployment" git push⚠️ IMPORTANT: Only do this if your repository is private!
-
Set Environment Variables in Dokploy:
- Navigate to your application in Dokploy
- Go to "Environment Variables" section
- Add all required variables (see Environment Variables)
-
Deploy:
- Click "Deploy" in Dokploy
- Wait for build and deployment to complete
- Check logs for any errors
Option 2: Using Dokploy Secrets Manager (Most Secure)
-
Upload SSH Key via Dokploy UI:
- Go to Dokploy → Secrets → Create New Secret
- Name:
SSH_PRIVATE_KEY - Content: Paste your SSH private key content
- Save
-
Modify
docker-compose.ymlto use the secret:roa-ssh-tunnel: secrets: - ssh_private_key # ... rest of config secrets: ssh_private_key: external: true -
Update Dockerfile to use mounted secret:
# Copy SSH key from mounted secret RUN --mount=type=secret,id=ssh_private_key \ cp /run/secrets/ssh_private_key /home/tunnel/.ssh/roa_oracle_server && \ chown tunnel:tunnel /home/tunnel/.ssh/roa_oracle_server && \ chmod 600 /home/tunnel/.ssh/roa_oracle_server
Detailed Setup
1. SSH Key Configuration
The SSH tunnel requires a private key to connect to the Oracle database server. Choose one of the following methods:
Method A: Include in Repository (Private Repos Only)
-
Prepare the SSH Key:
cd /mnt/e/proiecte/roa2web # Copy your SSH key to the secrets directory cp /path/to/your/roa_oracle_server ./ssh-tunnel/secrets/ # Set proper permissions chmod 600 ./ssh-tunnel/secrets/roa_oracle_server # Verify the key ls -l ./ssh-tunnel/secrets/roa_oracle_server -
Commit to Repository (ONLY if private!):
git add ssh-tunnel/secrets/roa_oracle_server git commit -m "Add SSH key for production deployment" git push origin main -
Test Locally:
# Test SSH connection ssh -i ./ssh-tunnel/secrets/roa_oracle_server \ -p 22122 \ roa2web@83.103.197.79 \ "echo 'Connection successful'" # Test Docker build docker build -t test-ssh-tunnel ./ssh-tunnel
Method B: Use Dokploy Environment Files
-
In Dokploy UI:
- Navigate to: Application → Settings → Environment Files
- Click "Add Environment File"
- File path:
/home/tunnel/.ssh/roa_oracle_server - Content: Paste your SSH private key
- Permissions:
600
-
Mount in
docker-compose.yml:roa-ssh-tunnel: volumes: - ${SSH_KEY_FILE}:/home/tunnel/.ssh/roa_oracle_server:ro
Method C: Use Docker BuildKit Secrets
-
In Dokploy Build Settings:
- Enable BuildKit
- Add build secret:
id=ssh_key,src=<path_to_key>
-
Update Dockerfile:
RUN --mount=type=secret,id=ssh_key \ cp /run/secrets/ssh_key /home/tunnel/.ssh/roa_oracle_server && \ chmod 600 /home/tunnel/.ssh/roa_oracle_server && \ chown tunnel:tunnel /home/tunnel/.ssh/roa_oracle_server
2. Environment Variables
Configure these environment variables in Dokploy:
Required Variables
| Variable | Description | Example |
|---|---|---|
ORACLE_USER |
Oracle database username | CONTAFIN_ORACLE |
ORACLE_PASSWORD |
Oracle database password | your_secure_password |
ORACLE_HOST |
Oracle host (via tunnel) | roa-ssh-tunnel (in Docker network) |
ORACLE_PORT |
Oracle port (via tunnel) | 1526 |
ORACLE_SID |
Oracle SID | ROA |
JWT_SECRET_KEY |
Secret key for JWT tokens | Generate: openssl rand -hex 32 |
JWT_ALGORITHM |
JWT algorithm | HS256 |
JWT_EXPIRE_MINUTES |
Token expiration time | 30 |
SSH Tunnel Variables
| Variable | Description | Example |
|---|---|---|
SSH_SERVER |
Remote SSH server | 83.103.197.79 |
SSH_PORT |
SSH port | 22122 |
SSH_USER |
SSH username | roa2web |
REMOTE_HOST |
Oracle database host (remote) | 10.0.20.36 |
REMOTE_PORT |
Oracle database port (remote) | 1521 |
Telegram Bot Variables (Optional)
| Variable | Description | Example |
|---|---|---|
TELEGRAM_BOT_TOKEN |
Telegram bot token from @BotFather | 123456:ABC-DEF... |
CLAUDE_API_KEY |
Claude API key for agent features | sk-ant-... |
TELEGRAM_LOG_LEVEL |
Logging level | INFO |
Optional Variables
| Variable | Description | Default |
|---|---|---|
ENVIRONMENT |
Environment name | production |
DEBUG |
Enable debug mode | false |
DOMAIN |
Domain for the application | roa2web.yourdomain.com |
SSL_EMAIL |
Email for Let's Encrypt SSL | admin@yourdomain.com |
REDIS_PASSWORD |
Redis password | roa2web_redis_password |
Setting Variables in Dokploy
- Go to your application in Dokploy
- Navigate to Settings → Environment Variables
- Click Add Environment Variable
- Add each variable one by one:
- Key:
ORACLE_PASSWORD - Value:
your_secure_password - Click Save
- Key:
- Repeat for all required variables
Alternative: Bulk Import
Create a .env file and import it:
# .env.production
ORACLE_USER=CONTAFIN_ORACLE
ORACLE_PASSWORD=your_secure_password
ORACLE_HOST=roa-ssh-tunnel
ORACLE_PORT=1526
ORACLE_SID=ROA
JWT_SECRET_KEY=your_generated_secret_key
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=30
SSH_SERVER=83.103.197.79
SSH_PORT=22122
SSH_USER=roa2web
REMOTE_HOST=10.0.20.36
REMOTE_PORT=1521
TELEGRAM_BOT_TOKEN=your_telegram_token
CLAUDE_API_KEY=your_claude_key
ENVIRONMENT=production
DEBUG=false
Then in Dokploy:
- Settings → Environment Variables → Import from file
- Upload
.env.production
3. Repository Setup
-
Connect Your Git Repository:
- In Dokploy, create a new application
- Choose "Docker Compose"
- Connect your Git repository:
- Repository URL:
https://gitea.romfast.ro/romfast/roa2web.git - Branch:
main(or your deployment branch) - Authentication: Add Git credentials if private repo
- Repository URL:
-
Configure Build Settings:
- Dockerfile Path: Not needed (using docker-compose.yml)
- Docker Compose File:
docker-compose.yml - Build Context: Repository root
- Enable BuildKit: ✅ (recommended for better caching)
-
Configure Deployment Settings:
- Auto-deploy: Enable if you want automatic deployments on git push
- Health Check: Enable to verify services are running
- Restart Policy:
unless-stopped
4. Deployment
Initial Deployment
-
Pre-deployment Checklist:
- ✅ SSH key is configured (Method A, B, or C)
- ✅ All environment variables are set
- ✅ Repository is connected and accessible
- ✅ Docker Compose file is valid
-
Start Deployment:
- In Dokploy dashboard, click Deploy
- Monitor the deployment logs
- Look for these success indicators:
✅ Cloning Custom Git ... ✅ Building services ... ✅ Starting services ... ✅ Health checks passing ...
-
Expected Build Time:
- First deployment: 5-10 minutes (depending on network and CPU)
- Subsequent deployments: 2-5 minutes (with caching)
Deployment Stages
-
Clone Repository:
Cloning Custom Git https://...@gitea.romfast.ro/romfast/roa2web.git -
Build Images:
roa-ssh-tunnel: SSH tunnel container (~1 min)roa-backend: FastAPI backend (~3 min)roa-frontend: Vue.js frontend (~4 min)roa-gateway: Nginx gateway (~1 min)roa-telegram-bot: Telegram bot (~2 min)
-
Start Services:
- Redis starts first
- SSH tunnel starts and establishes connection
- Backend waits for SSH tunnel health check
- Frontend starts
- Nginx gateway starts and routes traffic
- Telegram bot starts last
-
Health Checks:
- Each service runs its health check
- Deployment succeeds when all health checks pass
Post-Deployment
Verify Deployment
-
Check Service Status:
- In Dokploy, navigate to Containers
- Verify all services are "Running" (green status):
roa-gateway(Nginx)roa-backend(FastAPI)roa-frontend(Vue.js)roa-ssh-tunnel(SSH)roa-redis(Redis)roa-telegram-bot(Telegram)
-
Check Logs:
# In Dokploy UI, click on each container to view logs # SSH Tunnel should show: [INFO] SSH tunnel established: localhost:1526 -> 10.0.20.36:1521 [INFO] Tunnel is active and healthy # Backend should show: INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 # Frontend should show: VITE v5.x ready in XXX ms # Nginx should show: nginx: [notice] start worker processes -
Test Endpoints:
Health Check:
curl https://your-domain.com/health # Expected: {"status":"healthy"}API Health:
curl https://your-domain.com/api/health # Expected: {"status":"ok","database":"connected"}Frontend:
- Open
https://your-domain.comin browser - You should see the login page
- Open
-
Test Authentication:
curl -X POST https://your-domain.com/api/auth/login \ -H "Content-Type: application/json" \ -d '{"username":"test_user","password":"test_password"}' # Expected: {"access_token":"eyJ...","token_type":"bearer"} -
Test Database Connection:
# Check SSH tunnel logs docker logs roa-ssh-tunnel # Should show successful tunnel establishment # Should show periodic health checks passing
Configure DNS and SSL
-
DNS Setup:
- Point your domain to Dokploy server IP
- Add A record:
roa2web.yourdomain.com→<dokploy-server-ip>
-
SSL Certificate (if using custom domain):
- Dokploy typically handles SSL automatically via Let's Encrypt
- Or configure in
nginx/ssl/directory - Verify SSL:
https://www.ssllabs.com/ssltest/
-
Update Environment Variables:
- Set
DOMAIN=roa2web.yourdomain.com - Set
SSL_EMAIL=admin@yourdomain.com - Redeploy if needed
- Set
Configure Telegram Bot (Optional)
-
Test Bot:
- Open Telegram
- Search for your bot:
@your_bot_name - Send
/start - Should receive welcome message
-
Link Account:
- Login to web app
- Go to Settings → Telegram Integration
- Click "Generate Link Code"
- Copy the 8-character code
- Send to Telegram bot:
/start ABC123XY - Verify account is linked
-
Test Commands:
/help - Show available commands /companies - List accessible companies /dashboard - View financial dashboard
Monitoring and Maintenance
Monitor Services
-
Dokploy Dashboard:
- View real-time container status
- Monitor CPU/Memory/Disk usage
- Check logs for errors
-
Health Checks:
- Automatic health checks every 30 seconds
- Failed health checks trigger alerts
- Configure notifications in Dokploy settings
-
Logging:
- Centralized logs in Dokploy UI
- Filter by service, time, log level
- Export logs for analysis
Backup Strategy
-
Database Backups (Oracle):
- Handled by your Oracle DBA
- SSH tunnel only provides access, doesn't store data
-
Telegram Bot Database (SQLite):
# Backup SQLite database docker exec roa-telegram-bot cp /app/data/telegram_bot.db /app/data/backup/ # Download backup docker cp roa-telegram-bot:/app/data/backup/telegram_bot.db ./telegram_backup.db -
Configuration Backups:
- Environment variables: Export from Dokploy
- Docker Compose: Keep in Git
- SSH keys: Store securely offline
Update and Rollback
-
Update Application:
# Push changes to git git add . git commit -m "Update feature X" git push origin main # In Dokploy, click "Redeploy" # Or enable auto-deploy for automatic updates -
Rollback to Previous Version:
- In Dokploy → Deployments → History
- Find previous successful deployment
- Click "Rollback"
- Confirm rollback
-
Zero-Downtime Updates:
- Dokploy handles rolling updates automatically
- Old containers stay running until new ones are healthy
- Health checks ensure smooth transitions
Scaling
-
Horizontal Scaling (Multiple Instances):
# In docker-compose.yml roa-backend: deploy: replicas: 3 # Run 3 backend instances -
Vertical Scaling (More Resources):
roa-backend: deploy: resources: limits: cpus: '2.0' memory: 2G -
Load Balancing:
- Nginx gateway handles load balancing automatically
- Distributes traffic across backend replicas
- Health checks ensure traffic goes to healthy instances
Troubleshooting
Common Issues
1. SSH Tunnel Connection Failed
Error:
[ERROR] SSH connection failed: Permission denied (publickey)
Solutions:
a. Verify SSH Key:
# Check key exists and has correct permissions
docker exec roa-ssh-tunnel ls -l /home/tunnel/.ssh/roa_oracle_server
# Expected: -rw------- 1 tunnel tunnel
# Test SSH connection manually
docker exec roa-ssh-tunnel ssh -i /home/tunnel/.ssh/roa_oracle_server \
-p 22122 roa2web@83.103.197.79 "echo 'Connected'"
b. Verify SSH Key Format:
# Key should start with:
# -----BEGIN OPENSSH PRIVATE KEY-----
# or
# -----BEGIN RSA PRIVATE KEY-----
# Check key format
head -1 ./ssh-tunnel/secrets/roa_oracle_server
c. Check Remote Server:
- Verify public key is in
~/.ssh/authorized_keyson remote server - Verify SSH service is running on port 22122
- Check firewall allows connections from Dokploy server IP
2. Oracle Database Connection Failed
Error:
ORA-12170: TNS:Connect timeout occurred
Solutions:
a. Verify SSH Tunnel is Running:
# Check tunnel health
curl http://<dokploy-domain>/api/health
# Check tunnel logs
docker logs roa-ssh-tunnel
# Should show: "SSH tunnel established"
b. Test Oracle Connection:
# From backend container
docker exec roa-backend python -c "
import oracledb
conn = oracledb.connect(
user='CONTAFIN_ORACLE',
password='${ORACLE_PASSWORD}',
dsn='roa-ssh-tunnel:1526/ROA'
)
print('Connected successfully')
conn.close()
"
c. Check Environment Variables:
docker exec roa-backend env | grep ORACLE
# Verify all ORACLE_* variables are set correctly
3. Frontend Not Loading
Error:
502 Bad Gateway
Solutions:
a. Check Frontend Container:
# View frontend logs
docker logs roa-frontend
# Verify container is running
docker ps | grep roa-frontend
b. Check Nginx Configuration:
# Test nginx config
docker exec roa-gateway nginx -t
# View nginx logs
docker logs roa-gateway
c. Verify Network:
# Check containers can communicate
docker exec roa-gateway ping roa-frontend
docker exec roa-gateway ping roa-backend
4. Backend API Errors
Error:
{"detail":"Internal server error"}
Solutions:
a. Check Backend Logs:
docker logs roa-backend --tail 100
b. Check Database Connection:
# Test database query
docker exec roa-backend python -c "
from app.database import oracle_pool
async def test():
async with oracle_pool.get_connection() as conn:
cursor = conn.cursor()
cursor.execute('SELECT 1 FROM DUAL')
print(cursor.fetchone())
import asyncio
asyncio.run(test())
"
c. Check JWT Configuration:
docker exec roa-backend env | grep JWT
# Verify JWT_SECRET_KEY is set
5. Telegram Bot Not Responding
Error:
- Bot doesn't respond to commands
Solutions:
a. Check Bot Container:
# View bot logs
docker logs roa-telegram-bot --tail 100
# Check if bot is running
docker ps | grep telegram-bot
b. Verify Token:
# Check token is set
docker exec roa-telegram-bot env | grep TELEGRAM_BOT_TOKEN
# Test token validity
curl https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getMe
c. Check Backend Connection:
# Test internal API
docker exec roa-telegram-bot curl http://localhost:8002/internal/health
# Test backend connection
docker exec roa-telegram-bot curl http://roa-backend:8000/health
6. Environment Variables Not Loading
Error:
The "ORACLE_PASSWORD" variable is not set. Defaulting to a blank string.
Solutions:
a. Set in Dokploy UI:
- Go to Settings → Environment Variables
- Add missing variable
- Redeploy
b. Check Variable Names:
- Ensure no typos in variable names
- Variables are case-sensitive
- No leading/trailing spaces
c. Use .env File:
- Create
.envin project root - Import via Dokploy UI
- Redeploy
7. Build Failures
Error:
failed to solve: failed to calculate checksum
Solutions:
a. Clear Build Cache:
- In Dokploy → Settings → Advanced
- Click "Clear Build Cache"
- Redeploy
b. Check Dockerfile:
# Validate Dockerfiles locally
docker build -t test-backend ./reports-app/backend
docker build -t test-frontend ./reports-app/frontend
docker build -t test-tunnel ./ssh-tunnel
c. Check File Paths:
- Verify COPY paths in Dockerfiles
- Ensure files exist in repository
- Check .dockerignore isn't excluding needed files
Getting Help
If issues persist:
-
Check Logs:
# Get all container logs docker-compose logs > deployment_logs.txt -
Export Configuration:
# Export environment variables # (redact sensitive values before sharing) docker exec roa-backend env > backend_env.txt -
Contact Support:
- Include: logs, error messages, steps to reproduce
- Redact: passwords, tokens, API keys
- Provide: Dokploy version, OS, Docker version
-
Community Resources:
- Dokploy documentation: https://docs.dokploy.com
- ROA2WEB repository issues
- Docker documentation
Security Best Practices
-
SSH Keys:
- ✅ Use Ed25519 keys (more secure than RSA)
- ✅ Use unique keys for each environment
- ✅ Rotate keys periodically (every 6-12 months)
- ✅ Never commit private keys to public repositories
- ✅ Use secrets management for production
-
Environment Variables:
- ✅ Use strong, random JWT secret keys (32+ characters)
- ✅ Use complex Oracle passwords
- ✅ Don't log sensitive values
- ✅ Rotate credentials periodically
-
Network Security:
- ✅ Use HTTPS/SSL for all external connections
- ✅ Restrict SSH access by IP if possible
- ✅ Use Dokploy's firewall features
- ✅ Keep all software updated
-
Container Security:
- ✅ Run containers as non-root users (already configured)
- ✅ Use minimal base images (alpine)
- ✅ Scan images for vulnerabilities
- ✅ Keep Docker and Dokploy updated
-
Access Control:
- ✅ Use strong Dokploy admin password
- ✅ Enable 2FA on Git accounts
- ✅ Limit who has deployment access
- ✅ Audit access logs regularly
Performance Optimization
-
Enable Caching:
- Use Redis for session storage
- Enable browser caching in Nginx
- Use Docker build cache (BuildKit)
-
Resource Limits:
services: roa-backend: deploy: resources: limits: cpus: '1.0' memory: 1G reservations: cpus: '0.5' memory: 512M -
Database Connection Pooling:
- Already configured in
shared/database/oracle_pool.py - Default: 5 min connections, 20 max connections
- Adjust based on load
- Already configured in
-
Frontend Optimization:
- Production build already includes:
- Minification
- Tree-shaking
- Code splitting
- Compression (gzip/brotli)
- Production build already includes:
Next Steps
After successful deployment:
-
✅ Monitor for 24-48 hours:
- Check logs for errors
- Monitor resource usage
- Verify all features work
-
✅ Set up Alerts:
- Configure Dokploy notifications
- Set up health check alerts
- Monitor disk space
-
✅ Plan Backup Strategy:
- Schedule regular backups
- Test restore procedures
- Document backup locations
-
✅ Document Custom Configuration:
- Record any changes made
- Document environment-specific settings
- Share knowledge with team
-
✅ Performance Testing:
- Load test the application
- Optimize as needed
- Plan for scaling
Additional Resources
-
ROA2WEB Documentation:
README.md- Project overviewCLAUDE.md- Development guideDEPLOYMENT_GUIDE.md- General deployment guideARCHITECTURE_SCHEMA.md- Architecture details
-
Dokploy Resources:
- Documentation: https://docs.dokploy.com
- GitHub: https://github.com/dokploy/dokploy
- Community: Discord/Forums
-
Docker Resources:
- Docker Compose: https://docs.docker.com/compose/
- Docker Build: https://docs.docker.com/build/
- Best Practices: https://docs.docker.com/develop/dev-best-practices/
Conclusion
You should now have ROA2WEB successfully deployed on Dokploy! 🎉
For questions or issues, refer to the troubleshooting section or check the ROA2WEB repository documentation.
Happy deploying! 🚀