# Status [![Build Status](https://jenkins.wrigglyt.xyz/job/t2/badge/icon)](https://jenkins.wrigglyt.xyz/job/t2/) # Jenkins Docker Deploy Example A Statping-like status monitoring app that demonstrates a Jenkins pipeline for Docker build, push, and deploy. The app performs HTTP/HTTPS and TCP checks, stores history in SQLite, and provides a dashboard with reports. It may be useful for monitoring sites legitimately as well. ## App Features - **HTTP/HTTPS checks** – Ping URLs, measure response time and status code (success = 2xx) - **TCP checks** – Verify connectivity to host:port - **History storage** – SQLite database persists check results - **Reports** – Uptime %, avg/min/max latency, recent check history - **Authentication** – Session-based login; multi-user with admin-managed accounts ## Repository Structure ``` . ├── Jenkinsfile # Pipeline definition ├── Dockerfile # Application image ├── docker-compose.yml # Deployment compose (pulled by deploy host) ├── app.py # Entry point ├── app/ │ ├── main.py # Flask routes │ ├── models.py # SQLite schema │ ├── checker.py # HTTP/HTTPS and TCP check logic │ └── scheduler.py # APScheduler for periodic checks ├── templates/ # HTML templates ├── static/ # CSS ├── requirements.txt └── README.md ``` ## Manual Test ```bash # Build and run locally (set SECRET_KEY and ADMIN_* for auth) docker build -t myapp:test . docker run -p 8080:8080 -v $(pwd)/data:/app/data \ -e SECRET_KEY=dev-secret-change-in-production \ -e ADMIN_USER=admin -e ADMIN_PASSWORD=changeme \ myapp:test # Visit http://localhost:8080 and log in ``` Add services from the dashboard (e.g. `https://example.com`, `google.com:443` for TCP) and view reports. ### Authentication The app uses session-based authentication. On first run, if `ADMIN_USER` and `ADMIN_PASSWORD` are set and no users exist, an admin user is created. Admins can add more users at `/users`. Set `SECRET_KEY` to a random value (e.g. 32-byte hex) for production. ### Check Retention and Rollups To limit database growth, the app **rolls up** old checks into hourly aggregates, then prunes raw data: 1. **Rollup** (every 15 min): Checks older than `ROLLUP_AGE_HOURS` are aggregated into hourly buckets (total, success count, latency stats) and stored in `uptime_rollups`. Raw checks in those hours are deleted. 2. **Prune**: Keeps last `CHECK_RETENTION_COUNT` raw checks per service; optionally deletes by age. This lets you report accurate uptime over **90+ days** without storing millions of raw checks. Reports combine rollups (historical) + raw checks (recent). | Env var | Default | Description | |---------|---------|-------------| | `ROLLUP_AGE_HOURS` | 24 | Aggregate checks older than N hours into hourly buckets | | `CHECK_RETENTION_COUNT` | 5000 | Keep last N raw checks per service | | `CHECK_RETENTION_DAYS` | 0 (disabled) | Also delete checks older than N days | Example: keep 2000 raw checks per service and drop anything older than 30 days: ```bash docker run -e CHECK_RETENTION_COUNT=2000 -e CHECK_RETENTION_DAYS=30 ... ``` ## Jenkins Pipeline The pipeline: 1. **Builds** a Docker image 2. **Pushes** the image to a container registry (Gitea, Docker Hub, etc.) 3. **SSHs** to a deployment machine 4. **Clones** (or pulls) this repo to get `docker-compose.yml` 5. **Deploys** with `docker compose up -d` ### Prerequisites **Jenkins** - Docker installed and Jenkins agent in `docker` group - **Pipeline** and **SSH Agent** plugins - Git for cloning **Deploy Host** - Docker and Docker Compose installed - SSH access for the deploy user - If using a private registry: run `docker login` on the deploy host ### Adapting the Jenkinsfile for Your Own Repo Edit the `environment` block in `Jenkinsfile` for your setup: | Variable | Description | Example | |----------|-------------|---------| | `DOCKER_REGISTRY` | Registry hostname (no `https://`) | `git.wrigglyt.xyz` or `docker.io` | | `DOCKER_IMAGE` | Image path (org/repo) | `ryanv/myapp` | | `DEPLOY_HOST` | Deploy server hostname or IP | `10.0.11.3` | | `DEPLOY_USER` | SSH user on deploy host | `ryanv` | | `DEPLOY_PATH` | Path on deploy host for this app | `/opt/myapp` | | `GIT_REPO_URL` | Git repo URL (for deploy host to clone) | `https://git.wrigglyt.xyz/ryanv/myapp.git` | **Credential IDs** – Update these in the Jenkinsfile if you use different IDs: | Credential ID | Type | Who sets it up | |---------------|------|----------------| | `gitea_credentials` | Username/Password | **Each user** – your Gitea login for pushing images | | `deploy-ssh-key` | SSH Username with private key | **Shared** – one key for the deploy host, can be reused | > **Shared deploy host:** If you share a deploy host (e.g. a home server), you can reuse the same `deploy-ssh-key` credential—no need to create your own. Each person **must** add their own Gitea credentials in Jenkins for their pipeline job (Manage Jenkins → Credentials → Add → Username with password, ID `gitea_credentials`). Use your Gitea username and an access token with package read/write for the registry. ### Jenkins Credentials Setup 1. **`deploy-ssh-key`** (shared for the deploy host) - Kind: SSH Username with private key - ID: `deploy-ssh-key` - Username: matches `DEPLOY_USER` - Private key: RSA key in PEM format (`ssh-keygen -t rsa -b 4096 -m PEM`) - Public key must be in `~/.ssh/authorized_keys` on the deploy host 2. **`gitea_credentials`** (per user, for registry push) - Kind: Username with password - ID: `gitea_credentials` (or change `credentialsId` in the Jenkinsfile) - Username: your Gitea username - Password: your Gitea password or access token (token recommended) ### First-Time Deploy Host Setup On the deploy host: ```bash sudo mkdir -p /opt/myapp sudo chown ryanv:ryanv /opt/myapp sudo usermod -aG docker ryanv ``` If multiple users deploy to the same host, use separate paths (e.g. `/opt/myapp-alice`, `/opt/myapp-bob`) and update `docker-compose.yml` to use different ports for each app. The `docker-compose.yml` mounts `./data:/app/data` for SQLite persistence. The container runs as UID 1000. Ensure the data directory is writable: ```bash mkdir -p data chown 1000:1000 data ``` ### Dependency Audit Before deploying, run `make audit` (or `pip-audit`) to check for known vulnerabilities in dependencies. ### Branch Behavior - **main** → image tag `latest` - **other branches** → image tag `{BUILD_NUMBER}-{GIT_SHA}`