A personal ASP.NET Core website with small projects, experiments, football data, weather data and other things I want to host myself on my awesome RaspberyyPi
The project can run anyehere, can also be self-hosted with Docker, nginx, MariaDB and DuckDNS. Which I do!
- .NET 8
- ASP.NET Core MVC / Razor
- Entity Framework Core
- MariaDB
- Docker
- Docker Compose
- nginx
- Let’s Encrypt
- DuckDNS
Adrians/ ASP.NET Core application
Adrians/Program.cs Application startup/configuration
Adrians/appsettings.json Safe default configuration
docker-compose.yml Docker services
Dockerfile Standard Docker build
Dockerfile.pi Raspberry Pi/runtime-only Docker build
nginx/ nginx configuration
.env.example Example environment variables
Safe defaults live in:
Adrians/appsettings.json
This file should not contain real secrets, API keys, database passwords or machine-specific values.
Use .NET user secrets for local development secrets.
From the project folder:
cd .\Adrians
dotnet user-secrets initAdd local secrets:
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Port=3306;Database=xx;User=xx;Password=YourMomaXX;TreatTinyAsBoolean=false"
dotnet user-secrets set "Frost:ClientId" "<your-frost-client-id>"
dotnet user-secrets set "Frost:ClientSecret" "<your-frost-client-secret>"
dotnet user-secrets set "FootballData:ApiKey" "<your-football-data-api-key>"Check configured secrets:
dotnet user-secrets listDo not commit user secrets.
Docker Compose reads variables from a local .env file in the repository root.
Create one from the template:
cp .env.example .envExample:
MARIADB_DATABASE=adriansdb
MARIADB_USER=adrian
MARIADB_PASSWORD=change-me
MARIADB_ROOT_PASSWORD=change-me
FROST_CLIENT_ID=change-me
FROST_CLIENT_SECRET=change-me
FOOTBALLDATA_API_KEY=change-meDo not commit .env.
Recommended setup:
- Visual Studio
- .NET SDK
- Docker Desktop
- Git
git clone git@github.com:Vigdals/AdriansVevside.git
cd AdriansVevsidecopy .env.example .envEdit .env and set local database values.
For local development, simple throwaway values are fine:
MARIADB_DATABASE=adriansdb
MARIADB_USER=adrian
MARIADB_PASSWORD=change-me
MARIADB_ROOT_PASSWORD=change-meStart Docker Desktop first.
Then run from the repository root:
docker compose up -d mariadbCheck status:
docker compose psMariaDB should show as healthy.
Also check that Windows can reach the database:
Test-NetConnection localhost -Port 3306Expected:
TcpTestSucceeded : True
From the ASP.NET project folder:
cd .\Adrians
dotnet user-secrets initSet the local connection string:
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Port=3306;Database=adriansdb;User=adrian;Password=supersecret;TreatTinyAsBoolean=false"Set API credentials as needed:
dotnet user-secrets set "Frost:ClientId" "<your-frost-client-id>"
dotnet user-secrets set "Frost:ClientSecret" "<your-frost-client-secret>"
dotnet user-secrets set "FootballData:ApiKey" "<your-football-data-api-key>"From the repository root:
dotnet restore .\Adrians.sln
dotnet build .\Adrians.sln
dotnet run --project .\Adrians\Adrians.csprojOr run/debug the Adrians project directly from Visual Studio.
Start all services:
docker compose up -dStart only MariaDB for local development:
docker compose up -d mariadbCheck services:
docker compose psView logs:
docker logs --tail=100 adriansvevside
docker logs --tail=100 nginx
docker logs --tail=100 mariadbStop services:
docker compose downReset local Docker database data:
docker compose down -v
docker compose up -d mariadbThe site can be hosted on a Raspberry Pi using Docker Compose.
Basic request flow:
Internet
-> router
-> nginx
-> ASP.NET Core app
-> MariaDB
Recommended public ports:
80/tcp HTTP
443/tcp HTTPS
Only web traffic should be forwarded from the router. Do not expose admin tools such as Portainer, Dozzle, Glances or database ports to the internet.
On a Raspberry Pi, the app can be published locally and then copied into a smaller runtime image.
From the repository root:
rm -rf publish
dotnet publish Adrians/Adrians.csproj -c Release -o publish /p:UseAppHost=false
docker build -f Dockerfile.pi -t adriansvevside-web .
docker compose up -d web nginxCheck the site:
curl -I https://vigdalpi.duckdns.orgExpected:
HTTP/2 200
A simple self-hosted deployment flow is:
Develop on Windows
-> commit and push to GitHub
-> Raspberry Pi fetches latest main
-> publish .NET app
-> build runtime Docker image
-> restart web/nginx
-> health check
Example deployment script on the Raspberry Pi:
#!/bin/sh
set -eu
APP_DIR="/home/pi/AdriansVevside"
HEALTH_URL="https://vigdalpi.duckdns.org"
cd "$APP_DIR"
echo "== Fetch latest code =="
git fetch origin main
LOCAL_SHA="$(git rev-parse HEAD)"
REMOTE_SHA="$(git rev-parse origin/main)"
if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
echo "No changes: $(date -Is)"
exit 0
fi
echo "== Deploying $LOCAL_SHA -> $REMOTE_SHA =="
git reset --hard origin/main
echo "== Validate compose =="
docker compose config >/dev/null
echo "== Publish .NET app =="
rm -rf publish
dotnet publish Adrians/Adrians.csproj -c Release -o publish /p:UseAppHost=false
echo "== Build runtime image =="
docker build -f Dockerfile.pi -t adriansvevside-web .
echo "== Start services =="
docker compose up -d web nginx
echo "== Health check =="
for i in $(seq 1 30); do
if curl -fsSI "$HEALTH_URL" >/dev/null; then
echo "Health OK"
docker image prune -f >/dev/null
echo "Deploy OK: $REMOTE_SHA $(date -Is)"
exit 0
fi
sleep 2
done
echo "Health check failed"
docker compose ps
docker logs --tail=120 adriansvevside
docker logs --tail=80 nginx
exit 1Make it executable:
chmod 700 ~/deploy-adriansvevside.shRun it manually:
~/deploy-adriansvevside.shOptional cron job:
*/5 * * * * /home/pi/deploy-adriansvevside.sh >> /home/pi/deploy-adriansvevside.log 2>&1For automatic pull/deploy, use a read-only deploy key without passphrase.
Recommended SSH alias:
Host github-adriansvevside
HostName github.com
User git
IdentityFile ~/.ssh/adriansvevside_deploy
IdentitiesOnly yesSet the repository remote:
git remote set-url origin github-adriansvevside:Vigdals/AdriansVevside.gitTest:
git fetch origin mainError:
failed to connect to the docker API
Fix: start Docker Desktop and retry.
Warnings like:
The "MARIADB_PASSWORD" variable is not set
Fix: create .env in the repository root.
Check that MariaDB is running and published on localhost:
docker compose ps
Test-NetConnection localhost -Port 3306The compose file should publish MariaDB like this for local development:
ports:
- "127.0.0.1:3306:3306"Use user secrets on Windows:
dotnet user-secrets listExpected names:
ConnectionStrings:DefaultConnection
Frost:ClientId
Frost:ClientSecret
FootballData:ApiKey
Use .env / environment variables in Docker and on the Raspberry Pi.
- Do not commit
.env. - Do not commit API keys or passwords.
- Use user secrets for Windows development.
- Use environment variables for Docker/Pi deployments.
- Keep database and admin tools private.
- Only expose HTTP/HTTPS publicly.
This project is licensed under the MIT License. See LICENSE for details.