From 3de474fbd2515a5174a7078fbc2c62903df4e5a4 Mon Sep 17 00:00:00 2001 From: GeorgeWebberley Date: Tue, 27 Jan 2026 19:22:06 +0100 Subject: [PATCH] Initial commit --- .env.example | 4 +++ .gitignore | 3 ++ .woodpecker.yaml | 19 +++++++++++++ README.md | 67 +++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yaml | 34 +++++++++++++++++++++++ 5 files changed, 127 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 .woodpecker.yaml create mode 100644 README.md create mode 100644 docker-compose.yaml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..3400882 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +DOCKER_INFLUXDB_INIT_USERNAME=username +DOCKER_INFLUXDB_INIT_PASSWORD=password +DOCKER_INFLUXDB_INIT_ORG=orgName +DOCKER_INFLUXDB_INIT_BUCKET=bucketName \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cfbfa63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +node_modules/ +dist/ \ No newline at end of file diff --git a/.woodpecker.yaml b/.woodpecker.yaml new file mode 100644 index 0000000..27c502e --- /dev/null +++ b/.woodpecker.yaml @@ -0,0 +1,19 @@ +variables: + - &app_name "surf-hub" + +when: + event: [push] + branch: main + +steps: + deploy: + image: docker:28-cli + privileged: true + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /home/george:/home/george + environment: + APP_NAME: *app_name + commands: + - cp -r . /home/george/$APP_NAME/ + - docker compose -p $APP_NAME -f /home/george/$APP_NAME/docker-compose.yaml up -d --pull always --force-recreate \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2d65d7f --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# 🌊 Surf-Hub + +A self-hosted observability stack built to monitor and visualize real-time surf conditions. + +**Surf-Hub** demonstrates a "DevOps approach" to a personal hobby. Instead of checking manual forecasts, this project automates data collection and visualization using industry-standard tools like **Grafana**, **InfluxDB**, and **Node.js**. + +--- + +## 🚀 Overview + +The goal of this project is to create a persistent, historical record of local surf conditions (swell height, period, and wind) and display them in a high-visibility dashboard. + +### 🛠️ The Tech Stack +* **Backend:** Node.js (Service-oriented architecture) +* **Database:** InfluxDB 2.x (Time-series data storage) +* **Visualization:** Grafana +* **Deployment:** Docker / Docker Compose +* **Architecture:** Multi-platform builds via `docker buildx` for `linux/amd64` compatibility. + +--- + +## 📊 Dashboard Preview +*(Tip: Replace this with a screenshot of your Grafana dashboard once it's live!)* +> ![Dashboard Screenshot](https://via.placeholder.com/800x400?text=Grafana+Surf+Dashboard+Preview) + +--- + +## ⚙️ How It Works + +1. **Data Ingestion:** A Node.js service polls a weather/surf API (e.g., Open-Meteo) every hour. +2. **Time-Series Storage:** The data is normalized and pushed to **InfluxDB**, allowing for historical trend analysis. +3. **Visualization:** **Grafana** queries InfluxDB to render "Live Condition" tiles and time-series graphs. +4. **Containerization:** The entire stack is orchestrated via Docker Compose for easy deployment to any server. + +--- + +## 🛠️ Setup & Installation + +### Prerequisites +* Docker & Docker Compose +* An API key from your chosen surf/weather data provider + +### Quick Start +1. **Clone the repo:** + ```bash + git clone [https://github.com/your-username/surf-hub.git](https://github.com/your-username/surf-hub.git) + cd surf-hub +2. **Configure environment:** + Create a .env file with your API credentials and InfluxDB tokens. +3. **Deploy the stack:** + Create a .env file with your API credentials and InfluxDB tokens. + ```bash + docker compose up -d + ``` +4. **Build the Fetcher (Cross-Platform):** + Create a .env file with your API credentials and InfluxDB tokens. + ```bash + docker buildx build --platform linux/amd64 -t surf-fetcher:latest ./fetcher --load + ``` + +--- + +## 🚀 Lessons Learned + +- Implementing time-series data structures for fluctuating environmental data. +- Managing containerized environments and cross-architecture builds using buildx. +- Designing intuitive dashboards that provide "glanceable" information. \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..42c4799 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,34 @@ +services: + influxdb: + image: influxdb:2.7 + container_name: influxdb + restart: always + networks: + - web_traffic + volumes: + - influxdb_data:/var/lib/influxdb2 + environment: + - DOCKER_INFLUXDB_INIT_MODE=setup + - DOCKER_INFLUXDB_INIT_USERNAME=${DOCKER_INFLUXDB_INIT_USERNAME} + - DOCKER_INFLUXDB_INIT_PASSWORD=${DOCKER_INFLUXDB_INIT_PASSWORD} + - DOCKER_INFLUXDB_INIT_ORG=${DOCKER_INFLUXDB_INIT_ORG} + - DOCKER_INFLUXDB_INIT_BUCKET=${DOCKER_INFLUXDB_INIT_BUCKET} + + grafana: + image: grafana/grafana-oss:latest + container_name: grafana + restart: always + networks: + - web_traffic + depends_on: + - influxdb + volumes: + - grafana_data:/var/lib/grafana + +volumes: + influxdb_data: + grafana_data: + +networks: + web_traffic: + external: true \ No newline at end of file