Files
2026-04-25 13:02:42 +02:00

10 KiB

LA2 Eternal - Deployment Guide

Complete step-by-step guide for deploying the LA2 Eternal Lineage 2 server portal on a fresh Ubuntu server.

Prerequisites

  • Ubuntu 22.04 LTS or newer (Ubuntu 24.04 LTS recommended)
  • Root or sudo access
  • Minimum 2GB RAM, 10GB disk space
  • Internet connection

Step 1: Update System

sudo apt update && sudo apt upgrade -y

Step 2: Install Docker and Docker Compose

# Remove any old Docker versions
sudo apt remove -y docker docker-engine docker.io containerd runc

# Install prerequisites
sudo apt install -y ca-certificates curl gnupg lsb-release

# Add Docker's official GPG key
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# Set up Docker repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Verify installation
sudo docker --version
sudo docker compose version

# Add your user to docker group (optional, to run docker without sudo)
sudo usermod -aG docker $USER
newgrp docker

Step 3: Clone Project Repository

# Create directory for the project
mkdir -p /opt/la2eternal
cd /opt/la2eternal

# Clone the repository (replace with your actual repository URL)
git clone <your-repository-url> .

# Or if you have the project files locally, copy them
cp -r /path/to/project/* /opt/la2eternal/

Step 4: Configure Environment Variables

# Copy the example environment file
cp .env .env.local

# Edit the environment file with your settings
nano .env.local

Required Environment Variables:

# Portal Auth
JWT_SECRET=your-super-secret-jwt-key-change-this
JWT_EXPIRES_IN=8h

# Portal Database (SQLite - embedded, no external service needed)
DATABASE_URL=file:./dev.db

# Game Server Database (MSSQL)
GAME_SERVER_HOST=your-game-server-ip
GAME_SERVER_PORT=1433
GAME_SERVER_USER=sa
GAME_SERVER_PASSWORD=your_game_server_password
GAME_SERVER_DATABASE=lin2db

# Game World Database (MSSQL)
GAME_WORLD_HOST=your-game-server-ip
GAME_WORLD_PORT=1433
GAME_WORLD_USER=sa
GAME_WORLD_PASSWORD=your_game_server_password
GAME_WORLD_DATABASE=lin2world

# Server Info
SERVER_ID=1
SERVER_NAME=LA2 Eternal
SERVER_IP=your-server-public-ip
SERVER_PORT=7777

# Frontend
CORS_ORIGIN=http://localhost:5173
API_PORT=3001
REACT_PORT=5173
NODE_ENV=production
VITE_API_URL=http://your-server-ip:3001

Important: Change all default passwords before deploying!

Step 5: Build and Start Services

# Build all Docker images
sudo docker compose build

# Start all services in detached mode
sudo docker compose up -d

# Check if all containers are running
sudo docker compose ps

You should see:

  • la2_portal_api - Node.js API server (with SQLite database)
  • la2_portal_fe - React frontend

Step 6: Verify Deployment

# Check API health
curl http://localhost:3001/health

# Expected response:
# {"status":"ok","timestamp":"..."}

# View logs if needed
sudo docker compose logs -f api
sudo docker compose logs -f react

Step 7: Access the Website

Open your browser and navigate to:

# Install UFW if not already installed
sudo apt install -y ufw

# Allow SSH (don't lock yourself out!)
sudo ufw allow 22/tcp

# Allow HTTP
sudo ufw allow 80/tcp
sudo ufw allow 5173/tcp

# Allow API
sudo ufw allow 3001/tcp

# Enable firewall
sudo ufw enable

# Check status
sudo ufw status

Step 9: Setup Domain and SSL (Optional)

If you have a domain name and want to use HTTPS:

Install Nginx

sudo apt install -y nginx

Configure Nginx as Reverse Proxy

Create a new Nginx configuration:

sudo nano /etc/nginx/sites-available/la2eternal

Add the following configuration:

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

    # Frontend
    location / {
        proxy_pass http://localhost:5173;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    # API
    location /api {
        proxy_pass http://localhost:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    # Downloads
    location /downloads {
        alias /opt/la2eternal/public/downloads;
        autoindex off;
    }
}

Enable the site:

sudo ln -s /etc/nginx/sites-available/la2eternal /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Setup SSL with Let's Encrypt

# Install Certbot
sudo apt install -y certbot python3-certbot-nginx

# Obtain SSL certificate
sudo certbot --nginx -d your-domain.com -d www.your-domain.com

# Test automatic renewal
sudo certbot renew --dry-run

Step 10: Production Optimizations

Enable Auto-Restart for Docker

sudo systemctl enable docker

Create Systemd Service (Optional)

Create a systemd service for auto-start on boot:

sudo nano /etc/systemd/system/la2eternal.service

Add:

[Unit]
Description=LA2 Eternal Portal
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/la2eternal
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target

Enable the service:

sudo systemctl daemon-reload
sudo systemctl enable la2eternal.service
sudo systemctl start la2eternal.service

Testing (Docker)

Smoke Test Script

A test/smoke-test.sh script is included to verify the Docker deployment works end-to-end.

Run the smoke test after starting Docker:

# Make sure containers are running first
sudo docker compose up -d

# Run the smoke test
chmod +x test/smoke-test.sh
./test/smoke-test.sh

What the smoke test verifies:

  1. API container is reachable on port 3001
  2. Frontend container is reachable on port 5173
  3. API /auth/register accepts valid registration (alphanumeric username only)
  4. API /auth/login returns a JWT token
  5. API /auth/me returns the authenticated user profile
  6. API /auth/game-account returns game account status for the authenticated user

Manual Docker Verification

# 1. Build and start all services
sudo docker compose build
sudo docker compose up -d

# 2. Wait for API to be ready
sleep 5

# 3. Verify API is up
curl -s http://localhost:3001/health || echo "API health check not configured — try registering a test user instead"

# 4. Test registration (username must be alphanumeric)
curl -s -X POST http://localhost:3001/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"username":"testuser123","email":"test@example.com","password":"testpass123"}'

# 5. Test login
curl -s -X POST http://localhost:3001/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","password":"testpass123"}'

# 6. Verify frontend is serving
curl -s -o /dev/null -w "%{http_code}" http://localhost:5173
# Expected: 200

Running Tests in Docker (API)

# Access the API container shell
sudo docker exec -it la2_portal_api sh

# Inside the container, run type checks
npx tsc --noEmit

# Exit the container shell
exit

Running Tests in Docker (Frontend)

# Access the React container shell (if using dev image)
sudo docker exec -it la2_portal_fe sh

# Inside the container, run the build to verify no TypeScript errors
npm run build

# Exit the container shell
exit

Maintenance Commands

# View all running containers
sudo docker compose ps

# View logs
sudo docker compose logs -f

# Restart services
sudo docker compose restart

# Stop all services
sudo docker compose down

# Stop and remove all containers and volumes (WARNING: deletes database data)
sudo docker compose down -v

# Update and rebuild
sudo docker compose pull
sudo docker compose build
sudo docker compose up -d

# Backup SQLite database (from API container)
sudo docker exec la2_portal_api sh -c 'cp /app/dev.db /app/dev.db.backup.$(date +%Y%m%d)'
sudo docker cp la2_portal_api:/app/dev.db.backup.$(date +%Y%m%d) ./backup-$(date +%Y%m%d).db

# Restore SQLite database (to API container)
sudo docker cp ./backup-date.db la2_portal_api:/app/dev.db
sudo docker restart la2_portal_api

Troubleshooting

Container won't start

# Check logs
sudo docker compose logs [service-name]

# Check for port conflicts
sudo netstat -tulpn | grep 3001
sudo netstat -tulpn | grep 5173

# Restart specific service
sudo docker compose restart api

Database connection issues

# Check if SQLite database file exists
cd /home/user/Documents/LA2NodeJS/api && ls -la dev.db

# View API logs for database errors
sudo docker compose logs -f api

# Reset database (WARNING: deletes all data)
rm -f /home/user/Documents/LA2NodeJS/api/dev.db
# Restart API to recreate database with Prisma migrations
sudo docker compose restart api

Permission denied errors

# Fix Docker socket permissions
sudo chmod 666 /var/run/docker.sock

# Or add user to docker group
sudo usermod -aG docker $USER
newgrp docker

Out of disk space

# Clean up unused Docker images and containers
sudo docker system prune -a

# Check disk usage
sudo docker system df

Security Recommendations

  1. Change all default passwords in .env file
  2. Use strong JWT_SECRET (at least 32 random characters)
  3. Enable UFW firewall and only open necessary ports
  4. Keep system updated with sudo apt update && sudo apt upgrade
  5. Use SSL/HTTPS for production deployments
  6. Regular backups of the database
  7. Monitor logs for suspicious activity

Support

For issues or questions:

  • Check the logs: sudo docker compose logs -f
  • Verify environment variables in .env file
  • Ensure game server database is accessible from the web server
  • Check firewall rules if services are not accessible

License

This project is for private use only. All Lineage 2 assets and trademarks belong to NCSoft.