first commit

This commit is contained in:
MoonDev
2026-02-05 23:16:18 +03:00
commit 780e1a7f01
7 changed files with 403 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@@ -0,0 +1,38 @@
# Environment variables
.env
.env.local
.env.*.local
# SQLite database files
/data/*
# TLS certificates (private keys!)
/certs/*
# Docker volumes
caddy-data/
caddy-config/
# IDE
.idea/
.vscode/
*.swp
*.swo
*~
# OS files
.DS_Store
Thumbs.db
# Logs
*.log
logs/
# Build artifacts
/build/
/dist/
/target/
# Temporary files
*.tmp
*.temp
.cache/

30
Caddyfile Normal file
View File

@@ -0,0 +1,30 @@
{
auto_https off
}
:80 {
redir https://{host}{uri}
}
attestation.app:443 {
tls /etc/caddy/certs/attestation.app.crt /etc/caddy/certs/attestation.app.key
# Disable HSTS
header Strict-Transport-Security ""
# Serve static files (HTML, CSS, images, etc.)
root * /srv/static
file_server
# Proxy API endpoints to the attestation server
reverse_proxy /api/* attestation:8080
# Proxy Auditor app endpoints
reverse_proxy /auditor/* attestation:8080
# Enable logging
log {
output stdout
format json
}
}

63
Dockerfile Normal file
View File

@@ -0,0 +1,63 @@
FROM eclipse-temurin:21-jdk-jammy AS builder
WORKDIR /build
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
RUN git clone --depth 1 --recurse-submodules https://github.com/GrapheneOS/AttestationServer.git .
# Patch the server to bind to 0.0.0.0 instead of localhost (::1)
# This is required for Docker networking to work
RUN sed -i 's/new InetSocketAddress("::1", 8080)/new InetSocketAddress("0.0.0.0", 8080)/' \
src/main/java/app/attestation/server/AttestationServer.java
# Optional: Patch the domain if you want to use a custom domain
# Uncomment and modify the following line for your domain:
# RUN sed -i 's/attestation.app/your-domain.com/g' \
# src/main/java/app/attestation/server/AttestationServer.java
RUN chmod +x gradlew && ./gradlew build -x test --no-daemon
# Process static files (replace {{css|...}} and {{js|...}} templates with SRI hashes)
RUN apt-get update && apt-get install -y --no-install-recommends \
openssl sed \
&& rm -rf /var/lib/apt/lists/*
COPY process-static-docker.sh /tmp/process-static.sh
RUN chmod +x /tmp/process-static.sh && /tmp/process-static.sh
# --- Runtime ---
FROM eclipse-temurin:21-jre-jammy
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -r -s /bin/false -u 1000 attestation
WORKDIR /app
# Copy the custom sqlite4java native library from the submodule
# This is built with newer SQLite that supports STRICT tables
RUN mkdir -p /app/libs
COPY --from=builder /build/libs/sqlite4java-prebuilt/libsqlite4java-linux-amd64-1.0.392.so /app/libs/
# Copy all JARs from builder
COPY --from=builder /build/build/libs/*.jar ./libs/
# Copy processed static files
COPY --from=builder /build/static ./static-orig/
COPY entrypoint.sh .
RUN chmod +x /app/entrypoint.sh
# Create directories and set permissions
# /data - for SQLite databases
# /srv/static - for sharing static files with caddy
RUN mkdir -p /data /srv/static && \
chown -R attestation:attestation /app /data /srv/static
EXPOSE 8080
# Run as root initially to fix permissions, entrypoint will drop privileges
ENTRYPOINT ["/app/entrypoint.sh"]

148
README.md Normal file
View File

@@ -0,0 +1,148 @@
# GrapheneOS AttestationServer Docker
Dockerized deployment of [GrapheneOS AttestationServer](https://github.com/GrapheneOS/AttestationServer) for local attestation.
## Overview
This project provides a containerized setup for running your own GrapheneOS AttestationServer. It includes:
- **AttestationServer** - The main Java application handling attestations
- **Caddy** - Reverse proxy with HTTPS support
- **SQLite** - Local database storage for attestation data
## Prerequisites
Before running the server, ensure you have:
1. **Docker** and **Docker Compose** installed
2. **TLS certificates** for `attestation.app` domain in the `certs/` directory:
- `certs/attestation.app.crt` - Certificate file
- `certs/attestation.app.key` - Private key file
3. **DNS or hosts file configuration** to resolve `attestation.app` to your server
## Pre-Launch Setup
### 1. Prepare TLS Certificates
Place your TLS certificates for `attestation.app` in the `certs/` directory:
- `certs/attestation.app.crt` - Certificate
- `certs/attestation.app.key` - Private key
> **Note:** Certificate generation is up to you. You can use self-signed certificates for local testing or certificates from a trusted CA.
### 2. Configure DNS or Hosts File
The GrapheneOS Auditor app expects to connect to `attestation.app`. You must redirect this domain to your local server's IP address.
#### Option A: Local Machine (hosts file)
Edit your hosts file:
**Linux/macOS:**
```bash
sudo nano /etc/hosts
```
**Windows:**
```
C:\Windows\System32\drivers\etc\hosts
```
Add the following line (replace `192.168.1.100` with your server's IP):
```
192.168.1.100 attestation.app
```
#### Option B: Network-wide (DNS)
Configure your router or local DNS server (like Pi-hole or AdGuard) to resolve `attestation.app` to your server's IP address.
#### Option C: Android Device (root required)
If your Android device is rooted, edit `/system/etc/hosts`:
```bash
su
mount -o remount,rw /system
echo "192.168.1.100 attestation.app" >> /system/etc/hosts
mount -o remount,ro /system
```
**Important:** You must configure this on the Android device running the Auditor app, not just the server.
### 3. Create Data Directory
Ensure the data directory exists for persistent SQLite storage:
```bash
mkdir -p data
```
## Running the Server
### Build and Start
```bash
docker-compose up -d --build
```
This will:
1. Build the AttestationServer from source
2. Start the attestation service on port 8080 (internal)
3. Start Caddy reverse proxy on ports 80 and 443
### Check Status
```bash
docker-compose ps
docker-compose logs -f
```
### Stop the Server
```bash
docker-compose down
```
### Stop and Remove All Data
```bash
docker-compose down -v
rm -rf data/*.db data/*.db-*
```
## Usage
1. Ensure your Android device has `attestation.app` pointing to your server IP
2. Install [GrapheneOS Auditor](https://github.com/GrapheneOS/Auditor) app on your Android device
3. Open the Auditor app
4. The app will connect to your local attestation server instead of the official one
## Directory Structure
```
.
├── certs/ # TLS certificates
│ ├── attestation.app.crt
│ └── attestation.app.key
├── data/ # SQLite databases (persistent)
│ ├── attestation.db
│ └── samples.db
├── Caddyfile # Caddy reverse proxy config
├── Dockerfile # AttestationServer build
├── docker-compose.yml # Service orchestration
├── entrypoint.sh # Container entrypoint
└── process-static-docker.sh # Static file processor
```
## Security Considerations
- Keep your private key (`certs/attestation.app.key`) secure and never commit it to version control
- The `.gitignore` file excludes sensitive files like certificates and databases
- This setup is intended for **local/private use only**
- For production deployment, use properly signed certificates from a trusted CA
## License
This Docker setup follows the same license as the upstream [GrapheneOS AttestationServer](https://github.com/GrapheneOS/AttestationServer).

44
docker-compose.yml Normal file
View File

@@ -0,0 +1,44 @@
version: '3.8'
services:
attestation:
build: .
container_name: attestation-server
restart: unless-stopped
volumes:
# Persist SQLite databases (attestation.db and samples.db)
- ./data:/data
# Share static files with caddy (attestation copies, caddy serves)
- static-files:/srv/static
networks:
- internal
expose:
- "8080"
caddy:
image: caddy:2-alpine
container_name: attestation-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./certs:/etc/caddy/certs:ro
- caddy-data:/data
- caddy-config:/config
# Mount static files from shared volume
- static-files:/srv/static:ro
depends_on:
- attestation
networks:
- internal
volumes:
caddy-data:
caddy-config:
static-files:
networks:
internal:

45
entrypoint.sh Normal file
View File

@@ -0,0 +1,45 @@
#!/bin/bash
set -e
# Fix permissions on /data directory (runtime volume mount may have wrong ownership)
# This ensures the attestation user can write SQLite databases
if [ -d "/data" ]; then
chown -R attestation:attestation /data
chmod 755 /data
fi
# Copy static files to shared volume (if mounted)
if [ -d "/srv/static" ]; then
echo "Copying static files to shared volume..."
cp -r /app/static-orig/* /srv/static/
chown -R attestation:attestation /srv/static
echo "Static files copied."
fi
# Set working directory to /data where SQLite databases will be stored
# The application creates attestation.db and samples.db in the working directory
cd /data
JAR_FILE="/app/libs/attestation-server.jar"
if [ ! -f "$JAR_FILE" ]; then
echo "ERROR: Main JAR not found at $JAR_FILE!"
echo "Available JARs:"
ls -la /app/libs/
exit 1
fi
echo "Starting AttestationServer..."
echo "JAR: $JAR_FILE"
echo "Data directory: $(pwd)"
echo "Running as user: attestation (UID 1000)"
# Run with the sqlite4java library path, dropping privileges to attestation user
# Use setpriv to drop privileges while preserving environment
exec setpriv --reuid=attestation --regid=attestation --clear-groups \
java \
-Xmx512m \
-XX:+UseG1GC \
-XX:+ExitOnOutOfMemoryError \
-Djava.library.path=/app/libs \
-jar "$JAR_FILE"

35
process-static-docker.sh Normal file
View File

@@ -0,0 +1,35 @@
#!/bin/bash
set -e
mkdir -p static-tmp
cp -a static/* static-tmp/
declare -a replacements
while IFS= read -r file; do
[ -f "$file" ] || continue
hash=$(sha256sum "$file" | head -c 8)
sri_hash=sha256-$(openssl dgst -sha256 -binary "$file" | openssl base64 -A)
dest="$(dirname "$file")/$hash.$(basename "$file")"
rel_path="${file#*/}"
dest_path="${dest#*/}"
if [[ "$file" == *.css ]]; then
replacements+=("s@{{css|/$rel_path}}@<link rel=\"stylesheet\" href=\"/$dest_path\" integrity=\"$sri_hash\"/>@g")
elif [[ "$file" == *.js ]]; then
replacements+=("s@{{js|/$rel_path}}@<script type=\"module\" src=\"/$dest_path\" integrity=\"$sri_hash\"></script>@g")
fi
mv "$file" "$dest"
replacements+=("s@{{integrity|/$rel_path}}@$sri_hash@g")
replacements+=("s@{{path|/$rel_path}}@/$dest_path@g")
done < <(find static-tmp -type f \( -name "*.css" -o -name "*.js" \))
while IFS= read -r htmlfile; do
for rep in "${replacements[@]}"; do
sed -i "$rep" "$htmlfile"
done
done < <(find static-tmp -type f -name "*.html")
rm -rf static
mv static-tmp static