Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions AI_CONTRIBUTING_RULES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Global AI Agent Instructions (Jules)

**1. The "Living Wiki" Mandate:**
This repository maintains its documentation as a living wiki. The primary sources of truth are the `SYSTEM_ARCHITECTURE.md` and `SECURITY_ARCHITECTURE.md` files.

**2. Mandatory PR Checklist:**
For *every single Pull Request* you generate, regardless of the specific issue assigned to you, you MUST perform the following checks before committing:
* **Diff Review:** Analyze your proposed code changes.
* **Wiki Sync:** If your code alters the network flow, port configurations, authentication methods, database schemas, or deployment commands, you MUST open `SYSTEM_ARCHITECTURE.md`, `SECURITY_ARCHITECTURE.md` and all other markdown files in the root directory and `/docs/` directory to update the relevant sections to reflect your exact code changes. Also update the `docs/system_data_flow.svg` as appropriate.
* **Commit Inclusion:** The documentation updates must be included in the same commit/PR as the code changes. Do not submit a PR where the code and the architecture wiki are out of sync.

**3. Global Build Constraint:**
Whenever generating or modifying Dockerfiles for this project, you MUST ensure the font package is explicitly set to `fonts-freefont-ttf` to prevent downstream rendering failures.
274 changes: 274 additions & 0 deletions CONTAINERIZATION_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
# CONTAINERIZATION_PLAN.md - OSCAR Full Stack Containerization

This document outlines the proposal for migrating the OSCAR (Open Source Central Alarm Station) architecture to a fully containerized deployment model orchestrated by Docker Compose.

## 1. Proposed `docker-compose.yml`

The new `docker-compose.yml` will unify the PostGIS database, the OSH Backend, and the Caddy Reverse Proxy into a single orchestration unit.

### 1.1 Service Definitions

```yaml
services:
osh-postgis:
build:
context: ./dist/release/postgis
dockerfile: Dockerfile
image: oscar-postgis:latest
container_name: oscar-postgis-container
environment:
- POSTGRES_DB=gis
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
# Performance Tuning from .env
- POSTGRES_SHARED_BUFFERS=${DB_SHARED_BUFFERS:-128MB}
- POSTGRES_EFFECTIVE_CACHE_SIZE=${DB_EFFECTIVE_CACHE_SIZE:-512MB}
- POSTGRES_WORK_MEM=${DB_WORK_MEM:-4MB}
- POSTGRES_MAX_WAL_SIZE=${DB_MAX_WAL_SIZE:-1GB}
- POSTGRES_MAX_CONNECTIONS=${DB_MAX_CONNECTIONS:-50}
- POSTGRES_MAINTENANCE_WORK_MEM=${DB_MAINTENANCE_WORK_MEM:-64MB}
ports:
- "5432:5432"
volumes:
- ./pgdata:/var/lib/postgresql/data
secrets:
- db_password
networks:
- osh-internal
deploy:
resources:
limits:
memory: ${DB_MEM_LIMIT:-1G}
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d gis"]
interval: 10s
timeout: 5s
retries: 5

osh-backend:
build:
context: .
dockerfile: Dockerfile.osh
image: oscar-backend:latest
container_name: oscar-backend-container
environment:
- DB_HOST=${DB_HOST:-osh-postgis}
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
- KEYSTORE=./osh-keystore.p12
- KEYSTORE_TYPE=PKCS12
- TRUSTSTORE=./truststore.jks
- TRUSTSTORE_TYPE=JKS
- SHOW_CMD=true
# JVM Tuning from .env
- JAVA_OPTS=-Xmx${BACKEND_MEM_LIMIT:-2G} -Xms${BACKEND_MEM_LIMIT:-2G}
volumes:
- ./osh-node-oscar/config:/app/config
- ./osh-node-oscar/db:/app/db
- ./osh-node-oscar/files:/app/files
- ./osh-node-oscar/osh-keystore.p12:/app/osh-keystore.p12
- ./osh-node-oscar/.app_secrets:/app/.app_secrets
- ./osh-node-oscar/truststore.jks:/app/truststore.jks
secrets:
- db_password
networks:
- osh-internal
depends_on:
osh-postgis:
condition: service_healthy
deploy:
resources:
limits:
memory: ${BACKEND_MEM_LIMIT:-2G}
restart: unless-stopped
# Port 8282 is not exposed to the host network to ensure it's only accessible via the proxy
# For local debugging, it can be bound to 127.0.0.1:8282
ports:
- "127.0.0.1:8282:8282"

osh-proxy:
image: caddy:2-alpine
container_name: oscar-proxy-container
environment:
- TAILSCALE_DOMAIN=${TAILSCALE_DOMAIN:-}
- LOCAL_DOMAIN=${LOCAL_DOMAIN:-localhost}
ports:
- "80:80"
- "443:443"
volumes:
- ./caddy:/etc/caddy
- caddy_data:/data
- caddy_config:/config
- /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
- ./osh-node-oscar/osh-leaf.crt:/etc/caddy/certs/osh-leaf.crt:ro
- ./osh-node-oscar/osh-leaf.key:/etc/caddy/certs/osh-leaf.key:ro
networks:
- osh-internal
restart: unless-stopped

networks:
osh-internal:
driver: bridge

secrets:
db_password:
file: .db_password

volumes:
caddy_data:
caddy_config:
```

### 1.2 Internal Network Routing and Port Mappings
- **Isolation**: All services reside on the `osh-internal` bridge network.
- **osh-postgis**: Port 5432 is internal only.
- **osh-backend**: Port 8282 is bound specifically to `127.0.0.1` on the host, preventing external access except through the reverse proxy. Within the Docker network, it is reachable by `osh-proxy` at `http://osh-backend:8282`.
- **osh-proxy**: Ports 80 and 443 are exposed to the host for public/LAN access.

## 2. Proposed TLS & Routing Strategy (Caddy Dynamic Switching)

The Caddy reverse proxy will handle TLS termination and dynamic routing based on environment variables.

### 2.1 Caddyfile Structure

The Caddyfile will implement a "Dual-Listener" setup, ensuring the local LAN fallback is always active even if Tailscale is enabled.

**Main Caddyfile (`/etc/caddy/Caddyfile`):**
```caddy
{
# Global options
}

# 1. Local LAN Block (Always Active Fallback)
{$LOCAL_DOMAIN:localhost}, 127.0.0.1 {
# Forward headers to the backend
reverse_proxy https://osh-backend:8282 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
transport http {
tls_insecure_skip_verify
}
}

# Use local Java certificates for LAN encryption
tls /etc/caddy/certs/osh-leaf.crt /etc/caddy/certs/osh-leaf.key
}

# 2. Tailscale Block (Conditional Federated Access)
{$TAILSCALE_DOMAIN} {
@has_tailscale expression "{env.TAILSCALE_DOMAIN} != ''"
handle @has_tailscale {
# Forward headers to the backend
reverse_proxy https://osh-backend:8282 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
transport http {
tls_insecure_skip_verify
}
}

# Use Tailscale's automatic TLS
tls {
get_certificate tailscale
}
}
}
```

### 2.2 Operational Details
- **Dual-Listener Reliability**: Caddy simultaneously serves the local LAN/localhost IP and the Tailscale domain. If Tailscale fails or loses internet connectivity, operators can immediately fall back to the LAN address without restarting services.
- **Local Mode**: Uses the locally generated Java Leaf certificates (`osh-leaf.crt` and `osh-leaf.key`).
- **Federated Mode (Tailscale)**: Uses the `get_certificate tailscale` directive. This block is only active when `TAILSCALE_DOMAIN` is populated.
- **Header Forwarding**: Standard headers (`X-Forwarded-For`, `X-Forwarded-Proto`, etc.) are forwarded to ensure the OSH backend correctly identifies the client's origin.

## 3. Proposed Backend Dockerfile

The OSH Backend will be containerized using a lightweight Alpine-based Java image.

### 3.1 Dockerfile Structure

```dockerfile
# Dockerfile.osh
FROM eclipse-temurin:21-jre-alpine

# Set the working directory
WORKDIR /app

# GLOBAL BUILD CONSTRAINT: Explicitly set the font package to font-freefont
# GLOBAL BUILD CONSTRAINT: Bypass HTTPS for corporate SSL inspection during build
RUN sed -i 's/https/http/g' /etc/apk/repositories && \
apk update && \
apk add --no-cache font-freefont openssl bash && \
rm -rf /var/cache/apk/*

# Copy build artifacts
COPY ./osh-node-oscar/lib /app/lib
COPY ./osh-node-oscar/config /app/config
COPY ./osh-node-oscar/web /app/web
COPY ./osh-node-oscar/logback.xml /app/logback.xml

# The ENTRYPOINT ensures pre-launch checks (Local CA generation and fail-secure secret loading) run before the JVM starts
# JAVA_OPTS is used to pass memory limits from the .env file
ENTRYPOINT ["/bin/bash", "-c", "java -cp 'lib/*' com.botts.impl.security.LocalCAUtility && if [ ! -f .app_secrets ]; then echo 'CRITICAL ERROR: .app_secrets not found. Halting startup.'; exit 1; fi && export KEYSTORE_PASSWORD=$(head -n 1 .app_secrets) && java $JAVA_OPTS -Djavax.net.ssl.keyStorePassword=$KEYSTORE_PASSWORD -Djavax.net.ssl.trustStorePassword=$KEYSTORE_PASSWORD -cp 'lib/*' com.botts.impl.security.SensorHubWrapper ./config/config.json ./db"]
```

## 4. Scaled Deployment Profiles (.env Templates)

These profiles define the environment variables required to scale the system for different hardware scenarios.

### Scenario A: "Edge Node" (1 Lane, All-in-One)
**Hardware**: Raspberry Pi (4GB-8GB RAM)

```ini
DB_HOST=osh-postgis
BACKEND_MEM_LIMIT=2G
DB_MEM_LIMIT=1G
DB_MAX_CONNECTIONS=50
DB_SHARED_BUFFERS=128MB
DB_EFFECTIVE_CACHE_SIZE=512MB
DB_WORK_MEM=4MB
DB_MAX_WAL_SIZE=1GB
```

### Scenario B: "Tactical Hub" (10 Lanes / 20 Cameras, All-in-One)
**Hardware**: Powerful Laptop (16GB RAM)

```ini
DB_HOST=osh-postgis
BACKEND_MEM_LIMIT=8G
DB_MEM_LIMIT=4G
DB_MAX_CONNECTIONS=100
DB_SHARED_BUFFERS=1GB
DB_EFFECTIVE_CACHE_SIZE=3GB
DB_WORK_MEM=16MB
DB_MAX_WAL_SIZE=4GB
```

### Scenario C: "Enterprise Central Hub" (50 Lanes / 100 Cameras, Distributed LAN)
**Hardware**: Machine 1 (App Server, 16GB), Machine 2 (DB Server, 16GB)

**Machine 1 (Application Server) Profile**:
```ini
DB_HOST=<IP_ADDRESS_OF_MACHINE_2>
BACKEND_MEM_LIMIT=14G
# (DB variables omitted/ignored as PostGIS does not run on this machine)
```

**Machine 2 (Database Server) Profile**:
```ini
DB_MEM_LIMIT=14G
DB_MAX_CONNECTIONS=200
DB_SHARED_BUFFERS=4GB
DB_EFFECTIVE_CACHE_SIZE=10GB
DB_MAINTENANCE_WORK_MEM=1GB
DB_WORK_MEM=64MB
DB_MAX_WAL_SIZE=8GB
```

## 5. Global Build Constraint Acknowledgment
- **Font Package**: All Alpine-based Dockerfiles explicitly set the font package to `font-freefont`.
- **HTTP Bypass**: All `apk add` steps use `sed -i 's/https/http/g' /etc/apk/repositories` to ensure reliability behind corporate firewalls.
15 changes: 15 additions & 0 deletions MAPPING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Upstream to Oscar-Flat Mapping

This document defines how upstream modules are mapped into the flattened structure of the oscar-flat repository.

| Upstream Path | Oscar-Flat Path (Internal) |
|---------------|----------------------------|
| sensors/ | include/osh-oakridge-modules/sensors/ |
| services/ | include/osh-oakridge-modules/services/ |
| processing/ | include/osh-oakridge-modules/processing/ |
| tools/ | include/osh-oakridge-modules/tools/ |
| core/ | include/osh-core/ |
| addons/ | include/osh-addons/ |
| web/ | web/ |

Note: The integration branch 'integration/oscar-v3.1.0-upgrades-4785495677883353489' already follows this mapping.
61 changes: 53 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This repository combines all the OSH modules and dependencies to deploy the OSH
- [Java 21](https://www.oracle.com/java/technologies/downloads/#java21)
- [Oakridge Build Node Repository](https://github.com/Botts-Innovative-Research/osh-oakridge-buildnode)
- Node v22
- [Docker](https://docs.docker.com/get-docker/) (Required to run the PostGIS database system)

## Installation
Clone the repository and update all submodules recursively
Expand Down Expand Up @@ -44,25 +45,63 @@ After the build completes, it can be located in `build/distributions/`

Option 1: Command Line
```bash
unzip build/distributions/osh-node-oscar-1.0.zip
cd osh-node-oscar-1.0/osh-node-oscar-1.0
# Note: Replace <version> with the current version, e.g. 3.0.0
unzip build/distributions/osh-node-oscar-<version>.zip
cd osh-node-oscar-<version>/osh-node-oscar-<version>
```
```bash
tar -xf build/distributions/osh-node-oscar-1.0.zip
cd osh-node-oscar-1.0/osh-node-oscar-1.0
# Note: Replace <version> with the current version, e.g. 3.0.0
tar -xf build/distributions/osh-node-oscar-<version>.zip
cd osh-node-oscar-<version>/osh-node-oscar-<version>
```
Option 2: Use File Explorer
1. Navigate to `path/to/osh-oakridge-buildnode/build/distributions/`
2. Right-click `osh-node-oscar-1.0.zip`.
2. Right-click `osh-node-oscar-<version>.zip` (where `<version>` is the current release version, e.g. `3.0.0`).
3. Select **Extract All..**
4. Choose your destination, (or leave the default) and extract.
1. Launch the OSH node:
Run the launch script, "launch.sh" for linux/mac and "launch.bat" for windows.
1. Launch the OSH node and PostGIS Database:
The database management system is handled through Docker. The default launch scripts automatically build and run a PostGIS container using the `Dockerfile` located in `dist/release/postgis`, and then start the OSH node.
Run the launch script, `launch-all.sh` (or `launch.sh` within the `osh-node-oscar` folder directly if the database is already running) for linux, `launch-all-arm.sh` (or `launch-arm.sh` if it exists) for mac, and `launch-all.bat` (or `launch.bat`) for windows.
2. Access the OSH Node
- Remote: **[ip-address]:8282/sensorhub/admin**
- Locally: **http://localhost:8282/sensorhub/admin**

The default credentials to access the OSH Node are admin:admin. This can be changed in the Security section of the admin page.
### First-Time Setup
On first boot, OSCAR enters an **Uninitialized State** and requires configuration via a Setup Wizard.
1. Navigate to `http://localhost:8282/` or `http://localhost:8282/sensorhub/admin`.
2. You will be automatically redirected to the **Setup Wizard**.
3. **Create an Admin Password**: Set a strong password for the `admin` account.
4. **Configure TOTP**:
- Scan the displayed QR code with an authenticator app (Google Authenticator, Authy, etc.).
- **Important**: Save the secret key shown in the wizard!
- Use the **Test Code** form to verify your setup before proceeding.
5. Once complete, you will be redirected to the Admin UI login.

### Logging In
After initialization, use the following credentials:
- **Username**: `admin`
- **Password**: The password you set during the Setup Wizard.
- **Two-Factor Authentication**:
- If your browser or client supports it, enter your password as usual and provide the 6-digit TOTP code when prompted.
- If you are prompted for a single login by the browser and can't provide a TOTP code separately, enter your password followed by a colon and the code (e.g., `mypassword:123456`).

**Language Selection**
The user can select different languages for the Admin UI by using the language drop-down menu located in the top right corner of the Admin UI toolbar. Selecting a new language will instantly switch the UI localization.

**Two-Factor Authentication (2FA)**
2FA is mandatory for the administrator account and can be configured for other users to add an extra layer of security. To set this up for additional users:
1. Log in to the Admin UI as `admin`.
2. Navigate to the **Security** section.
3. Edit a user profile and set up Two-Factor Authentication. A popup window will appear with a QR code generated locally on the server.
4. Scan the QR code with an authenticator app (like Google Authenticator or Authy) to complete the setup.

**Importing/Exporting Lane Configurations via CSV**
Configurations for Lane Systems can be bulk managed via spreadsheet (CSV).
1. Log in to the Admin UI.
2. Navigate to **Services -> OSCAR Service**.
3. Within the configuration form for the OSCAR service, locate the property for spreadsheet configuration (`spreadsheetConfigPath`).
4. To export, click the download button to retrieve the current configurations as a CSV file.
5. To import, upload your modified CSV file through the provided upload mechanism in the service configuration to apply new or updated lane setups.

For documentation on configuring a Lane System on the OSH Admin panel, please refer to the OSCAR Documentation provided in the Google Drive documentation folder.

Expand All @@ -73,6 +112,12 @@ After configuring the Lanes on the OSH Admin Panel, you can navigate to the Clie

For documentation on configuring a server on the OSCAR Client refer to the OSCAR Documentation provided in the Google Drive documentation folder.

## Security and Federation
- [Security Architecture](SECURITY_ARCHITECTURE.md)
- [System Architecture](SYSTEM_ARCHITECTURE.md)
- [Federation Provisioning (API Keys)](docs/FEDERATION_PROVISIONING.md)
- [Tailscale Security and Configuration](docs/TAILSCALE_CONFIGURATION.md)

# Release Checklist
- Version in `build.gradle`
- Version in `dist/config/standard/config.json`
Expand Down
Loading