# Ubuntu Server Setup

Simple setup guide for deploying Offline Maps Management on an Ubuntu server.

This guide assumes:
- PostgreSQL is already installed on the server.
- Redis will run with Docker.
- Backend and admin dashboard will run with Docker Compose.

## 1. Install Required Packages

```bash
sudo apt update
sudo apt install -y git curl unzip ca-certificates
```

Install Docker:

```bash
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
```

Log out and log in again, then verify:

```bash
docker --version
docker compose version
```

## 2. Create PostgreSQL Database

Login to PostgreSQL:

```bash
sudo -u postgres psql
```

Create database and user:

```sql
CREATE DATABASE offline_maps;
CREATE USER offline_maps_user WITH ENCRYPTED PASSWORD 'change_this_password';
GRANT ALL PRIVILEGES ON DATABASE offline_maps TO offline_maps_user;
\q
```

Allow Docker containers to connect to host PostgreSQL if needed.

Edit PostgreSQL config:

```bash
sudo nano /etc/postgresql/*/main/postgresql.conf
```

Set:

```conf
listen_addresses = '*'
```

Edit pg_hba:

```bash
sudo nano /etc/postgresql/*/main/pg_hba.conf
```

Add a trusted server subnet rule. Example:

```conf
host    offline_maps    offline_maps_user    172.16.0.0/12    md5
```

Restart PostgreSQL:

```bash
sudo systemctl restart postgresql
```

## 3. Upload Project To Server

Example path:

```bash
sudo mkdir -p /var/www/offline-maps-management
sudo chown -R $USER:$USER /var/www/offline-maps-management
```

Copy or clone the project:

```bash
cd /var/www
git clone <your-repo-url> offline-maps-management
cd offline-maps-management
```

If you are copying from local:

```bash
rsync -av --exclude node_modules --exclude dist ./ user@server:/var/www/offline-maps-management/
```

## 4. Configure Backend Env

```bash
cp backend/.env.example backend/.env
nano backend/.env
```

Use this pattern:

```env
DATABASE_URL=postgresql://offline_maps_user:change_this_password@host.docker.internal:5432/offline_maps?schema=public

JWT_ACCESS_SECRET=change-this-long-random-string
JWT_REFRESH_SECRET=change-this-long-random-string
JWT_ACCESS_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d

AWS_REGION=us-east-2
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_S3_BUCKET=your-bucket-name
AWS_S3_PUBLIC=false
AWS_SIGNED_URL_EXPIRES_IN=3600
CLOUDFRONT_DOMAIN=
CLOUDFRONT_ENABLED=false

REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=

PORT=3000
CORS_ORIGIN=http://your-server-ip:5173

PUBLIC_API_KEY=change-this-long-random-string
INTERNAL_CRYPTO_API_KEY=change-this-long-random-string
PUBLIC_CRYPTO_SECRET=change-this-long-random-string-at-least-40-chars
PUBLIC_AES_IV=offline-maps-api-iv
PUBLIC_API_PLAINTEXT_ALLOWED=false

MAX_UPLOAD_SIZE_BYTES=5368709120

ADMIN_NAME=Default Admin
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=ChangeMe123!
```

Generate random secrets:

```bash
openssl rand -base64 64
```

## 5. Configure Admin Dashboard Env

```bash
cp admin-dashboard/.env.example admin-dashboard/.env
nano admin-dashboard/.env
```

Set backend URL:

```env
VITE_API_BASE_URL=http://your-server-ip:3000
```

## 6. Update Docker Compose For Host PostgreSQL

The backend container must reach PostgreSQL installed on Ubuntu.

In `docker-compose.yml`, add this under the `backend` service:

```yaml
extra_hosts:
  - "host.docker.internal:host-gateway"
```

Start only Redis, backend, and dashboard:

```bash
docker compose up -d redis backend admin-dashboard --build
```

## 7. Run Database Migration And Seed Admin

```bash
docker compose exec backend npx prisma migrate deploy
docker compose exec backend npm run seed
```

## 8. Open App

Backend:

```text
http://your-server-ip:3000
```

Swagger:

```text
http://your-server-ip:3000/docs
```

Admin dashboard:

```text
http://your-server-ip:5173
```

Login with:

```text
ADMIN_EMAIL
ADMIN_PASSWORD
```

from `backend/.env`.

## 9. S3 CORS

Your S3 bucket must allow the dashboard origin.

Example `s3-cors.json`:

```json
[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "HEAD", "PUT", "POST"],
    "AllowedOrigins": ["http://your-server-ip:5173"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3000
  }
]
```

Apply with AWS CLI:

```bash
aws s3api put-bucket-cors \
  --bucket your-bucket-name \
  --cors-configuration file://s3-cors.json \
  --region us-east-2
```

If AWS CLI is not installed:

```bash
sudo apt install -y awscli
aws configure
```

## 10. Useful Commands

View logs:

```bash
docker compose logs -f backend
docker compose logs -f admin-dashboard
docker compose logs -f redis
```

Restart:

```bash
docker compose restart backend
docker compose restart admin-dashboard
```

Rebuild after code changes:

```bash
docker compose up -d backend admin-dashboard --build
```

Stop:

```bash
docker compose down
```

## 11. Sync Existing S3 Files To Database

If ZIP files were uploaded manually in AWS console, run:

```bash
curl -X POST "http://your-server-ip:3000/offline-maps/sync-s3" \
  -H "Authorization: Bearer <admin_access_token>" \
  -H "Content-Type: application/json" \
  -d '{"prefix":"offline-maps/","status":"ACTIVE"}'
```

Expected S3 path:

```text
offline-maps/india/andhra-pradesh/file.zip
```

## 12. Common Issues

### CORS Error In Browser

Add dashboard URL to `backend/.env`:

```env
CORS_ORIGIN=http://your-server-ip:5173
```

Then restart backend:

```bash
docker compose restart backend
```

### S3 Upload Network Error

Update S3 CORS and make sure `ExposeHeaders` contains:

```json
["ETag"]
```

### Backend Cannot Connect To PostgreSQL

Check:

```bash
docker compose logs -f backend
```

Verify `DATABASE_URL` uses:

```text
host.docker.internal
```

and backend service has:

```yaml
extra_hosts:
  - "host.docker.internal:host-gateway"
```

### Port Already Used

Check ports:

```bash
sudo lsof -i :3000
sudo lsof -i :5173
```

Stop old process or change ports in `docker-compose.yml`.

