immersive2/ALPINE_SERVICE.md
Michael Mainguy e2216c17e8
Some checks failed
Build and Deploy / build (push) Failing after 1m44s
Node.js CI / build (push) Has been cancelled
Add Alpine Linux service setup and CI/CD deployment
- Add ALPINE_SERVICE.md with full setup instructions
- Add start.sh script for OpenRC service
- Update build.yml for deployment to /opt/immersive
- Configure proper permissions for immersive user
- Add Gitea runner setup instructions with sudo config
- Add .env.production to gitignore

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 09:21:08 -06:00

6.0 KiB

Alpine Linux Service Setup

This guide covers installing and running Immersive as a service on Alpine Linux using OpenRC.

Prerequisites

# Update packages
apk update

# Install Node.js 18+ and npm
apk add nodejs npm

# Install build dependencies (required for native modules like leveldown)
apk add python3 make g++ git

# Verify Node version (must be >= 18)
node --version

Create Service User

Create a dedicated user to run the service (security best practice):

# Create immersive group and user (no login shell, no home directory)
addgroup -S immersive
adduser -S -G immersive -H -s /sbin/nologin immersive

# Create directories with proper ownership
mkdir -p /opt/immersive
mkdir -p /var/log/immersive
mkdir -p /var/run/immersive

chown -R immersive:immersive /opt/immersive
chown -R immersive:immersive /var/log/immersive
chown -R immersive:immersive /var/run/immersive

Installation

# Create application directory
mkdir -p /opt/immersive
cd /opt/immersive

# Clone or copy the application
git clone <your-repo-url> .
# OR copy files manually

# Install dependencies
npm ci --production=false

# Build the application
NODE_OPTIONS='--max-old-space-size=4096' npm run build

# Copy Havok physics WASM (if not already done by build)
npm run havok

# Create data directory for PouchDB
mkdir -p /opt/immersive/data

# Set ownership to immersive user
chown -R immersive:immersive /opt/immersive

Start Script

The start.sh script is included in the repository. After deployment, ensure it's executable:

chmod +x /opt/immersive/start.sh

The script sets up the environment and starts the Node.js server, logging output to /var/log/immersive/.

OpenRC Service

Create /etc/init.d/immersive:

#!/sbin/openrc-run

name="immersive"
description="Immersive WebXR Diagramming Application"

command="/opt/immersive/start.sh"
command_user="immersive:immersive"
command_background="yes"
pidfile="/var/run/immersive/immersive.pid"

directory="/opt/immersive"
output_log="/var/log/immersive/app.log"
error_log="/var/log/immersive/error.log"

depend() {
    need net
    after firewall
}

start_pre() {
    checkpath --directory --owner immersive:immersive --mode 0755 /var/log/immersive
    checkpath --directory --owner immersive:immersive --mode 0755 /var/run/immersive
    checkpath --file --owner immersive:immersive --mode 0644 /var/log/immersive/app.log
    checkpath --file --owner immersive:immersive --mode 0644 /var/log/immersive/error.log
}

Make it executable and enable:

chmod +x /etc/init.d/immersive
rc-update add immersive default

Service Management

# Start the service
rc-service immersive start

# Stop the service
rc-service immersive stop

# Restart the service
rc-service immersive restart

# Check status
rc-service immersive status

# View logs
tail -f /var/log/immersive/app.log
tail -f /var/log/immersive/error.log

Log Rotation

Create /etc/logrotate.d/immersive:

/var/log/immersive/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 0644 immersive immersive
    postrotate
        rc-service immersive restart > /dev/null 2>&1 || true
    endscript
}

Install logrotate if not present:

apk add logrotate

Environment Variables

Create /opt/immersive/.env.production for production settings:

# Server
NODE_ENV=production
PORT=3001

# Auth0 (if using authentication)
# VITE_AUTH0_DOMAIN=your-domain.auth0.com
# VITE_AUTH0_CLIENT_ID=your-client-id

# Database sync endpoint (optional)
# VITE_SYNCDB_ENDPOINT=https://your-couchdb-server.com

Firewall (if using iptables)

# Allow port 3001
iptables -A INPUT -p tcp --dport 3001 -j ACCEPT

# Save rules
rc-service iptables save

Reverse Proxy (Optional)

If using nginx as a reverse proxy:

apk add nginx

Create /etc/nginx/http.d/immersive.conf:

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://127.0.0.1:3001;
        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;
    }
}

Enable and start nginx:

rc-update add nginx default
rc-service nginx start

Gitea CI/CD Runner (Optional)

If using a Gitea Actions runner to deploy, grant the runner user write access to /opt/immersive:

# Add gitea-runner to immersive group
adduser gitea-runner immersive

# Set group write permissions on /opt/immersive
chmod -R g+w /opt/immersive

# Ensure new files inherit group ownership
chmod g+s /opt/immersive

# Allow runner to manage the service
# Add to /etc/sudoers.d/gitea-runner:
echo 'gitea-runner ALL=(ALL) NOPASSWD: /sbin/rc-service immersive *' > /etc/sudoers.d/gitea-runner
echo 'gitea-runner ALL=(ALL) NOPASSWD: /bin/chown -R immersive\:immersive /opt/immersive' >> /etc/sudoers.d/gitea-runner
chmod 440 /etc/sudoers.d/gitea-runner

The GitHub Actions workflow in .github/workflows/build.yml will handle deployment automatically on push to main.

Troubleshooting

Service fails to start:

# Check logs
cat /var/log/immersive/error.log

# Run manually as immersive user to see errors
su -s /bin/sh immersive -c "cd /opt/immersive && NODE_ENV=production node server.js"

Native module errors (leveldown):

# Rebuild native modules
cd /opt/immersive
npm rebuild leveldown

Permission issues:

# Ensure proper ownership (must be immersive user)
chown -R immersive:immersive /opt/immersive
chown -R immersive:immersive /var/log/immersive
chown -R immersive:immersive /var/run/immersive
chmod -R 755 /opt/immersive

Port already in use:

# Find process using port 3001
lsof -i :3001
# Or
netstat -tlnp | grep 3001