This repository uses GitHub Actions for automated testing and deployment. The workflow is defined in .github/workflows/nodejs-cicd.yml.
- Trigger: Push to
mainbranch or pull requests todevelopmentbranch - Test Job: Runs on
ubuntu-latest, tests with Node.js 24 - Deploy Job: Runs on specified runner after tests pass
The following secrets must be configured in GitHub repository settings (Settings > Secrets and variables > Actions):
- TPEN_EMAIL_CC (Optional)
- Description: Email address to CC on notifications
- Format: Email address
- Used by: CI/CD workflow for notifications
If the deploy job uses SSH to deploy to remote servers, configure:
-
SSH_PRIVATE_KEY
- Description: Private SSH key for deploying to the target machine
- Format: Full SSH private key (RSA or ED25519)
- Example generation:
ssh-keygen -t ed25519 -C "github-actions@inbox" - The corresponding public key must be added to
~/.ssh/authorized_keyson the target server
-
SSH_HOST
- Description: Hostname or IP address of the target deployment machine
- Format: Hostname or IP address
- Example:
tpen-services.example.comor192.168.1.100
-
SSH_USER
- Description: Username for SSH connection to the target machine
- Format: Unix username
- Example:
deployortpen
-
DEPLOY_PATH
- Description: Absolute path on the server where the application should be deployed
- Format: Absolute path
- Example:
/opt/inboxor/home/tpen/apps/inbox - Note: This directory will be created if it doesn't exist
The application supports the following environment variables:
- PORT: Port number for the application (default: 3000)
- ID_ROOT: Base URL for generated IDs (default:
http://inbox.rerum.io) - NODE_ENV: Runtime environment (development or production, default: production)
Configure environment variables in PM2 ecosystem file or systemd service:
Create ecosystem.config.js in the deployment directory:
module.exports = {
apps: [{
name: 'inbox',
script: './server.js',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: 'production',
PORT: 3000,
ID_ROOT: 'http://inbox.rerum.io'
}
}]
};Start with: pm2 start ecosystem.config.js
The CI/CD pipeline automatically:
- Tests the application on every push to
mainand pull requests todevelopment - Deploys to the configured runners after tests pass
- Validates the deployment by waiting for the service to be ready
To deploy to your DEV and PRD servers, you need to set up self-hosted GitHub Actions runners:
-
On the DEV server:
# Follow GitHub Actions runner setup documentation # https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners
-
On the PRD server:
# Same setup as DEV -
Configure runner labels for DEV and PRD environments
-
Update
.github/workflows/nodejs-cicd.ymlto specify runner labels:deploy-dev: runs-on: [self-hosted, dev-runner] deploy-prd: runs-on: [self-hosted, prd-runner]
If deploying manually without GitHub Actions:
-
Clone or copy the repository to the server
cd /opt git clone https://github.com/CenterForDigitalHumanities/inbox.git cd inbox
-
Install dependencies
npm ci --production
-
Start with PM2
pm2 start server.js --name inbox pm2 save pm2 startup # Configure PM2 to start on boot -
Configure Apache/Nginx as described below
-
Restart the web server
sudo systemctl restart apache2 # or sudo systemctl restart nginx
The deployment server must have:
-
Node.js (v18 or later, v20+ recommended)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt-get install -y nodejs -
PM2 (Process Manager for Node.js)
sudo npm install -g pm2
-
SSH Access (if using SSH deployment)
- SSH daemon running
- Public key authentication configured
- Deploy user has permission to write to DEPLOY_PATH
The application runs on port 3000 by default. Configure your reverse proxy (Apache or Nginx) to route traffic to this port.
Add the following configuration to your Apache virtual host configuration (typically in /etc/apache2/sites-available/):
# Enable required modules
# Run: sudo a2enmod proxy proxy_http headers
<VirtualHost *:80>
ServerName inbox.rerum.io
# Proxy settings
ProxyPreserveHost On
ProxyPass /inbox http://localhost:3000
ProxyPassReverse /inbox http://localhost:3000
# Optional: Add headers
<Location /inbox>
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type"
</Location>
# Handle OPTIONS requests for CORS
<Location /inbox>
<IfModule mod_headers.c>
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Content-Type"
</IfModule>
</Location>
</VirtualHost>Previous Java Configuration:
- Application ran on Tomcat (typically port 8080)
- Context path was defined in
web/META-INF/context.xml - Required Tomcat-specific deployment descriptors
- Deployed via GitHub Actions without self-hosted runners
New Node.js Configuration:
- Application runs directly on port 3000
- No context.xml or deployment descriptors needed
- Simpler proxy configuration
- Built-in CORS support in application
- Deployed via GitHub Actions with self-hosted runners on DEV/PRD servers
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
sudo systemctl restart apache2If using Nginx instead of Apache:
server {
listen 80;
server_name inbox.rerum.io;
location /inbox {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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;
proxy_cache_bypass $http_upgrade;
# CORS headers
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type" always;
}
}The application provides a health check endpoint:
curl http://localhost:3000/healthResponse:
{
"status": "ok",
"timestamp": "2024-01-29T23:00:00.000Z"
}View application logs:
pm2 logs inboxMonitor application status:
pm2 status
pm2 monit- Check Node.js version:
node --version(should be 18+) - Check for port conflicts:
lsof -i :3000 - Review logs:
pm2 logs inbox --lines 100
- Verify modules are enabled:
apache2ctl -M | grep proxy - Check Apache error logs:
sudo tail -f /var/log/apache2/error.log - Verify the app is running:
curl http://localhost:3000/health
- Check runner status: Repository Settings > Actions > Runners
- Verify runner has Node.js 24 installed
- Review workflow logs in GitHub Actions tab
- Ensure deploy secrets are correctly configured