Base commit
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
hdd0
|
||||
hdd0_backups
|
||||
cache
|
||||
.env
|
||||
letsencrypt
|
||||
website-pro
|
||||
config/gitea/conf
|
29
README.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Self-Hosted Services
|
||||
|
||||
This repository contains my personal Docker Compose configuration for various self-hosted services, all exposed via Traefik. It serves primarily as a personal deployment configuration and a reference for others.
|
||||
|
||||
---
|
||||
|
||||
### Services Included:
|
||||
|
||||
- **Traefik:** Reverse proxy and load balancer with automatic HTTPS.
|
||||
- **Prometheus:** Monitoring system.
|
||||
- **Grafana:** Data visualization and dashboarding for Prometheus.
|
||||
- **cAdvisor:** Container resource usage and performance analysis.
|
||||
- **Node Exporter:** Exposes hardware and OS metrics for Prometheus.
|
||||
- **Fail2Ban:** Intrusion prevention for various services.
|
||||
- **Vaultwarden:** Unofficial Bitwarden server implementation.
|
||||
- **Kopia:** Fast, secure, and incremental backups.
|
||||
- **Memos:** A privacy-first, lightweight note-taking service.
|
||||
- **Jellyfin:** Free software media system.
|
||||
- **Filebrowser:** Web interface to browse and manage files.
|
||||
- **Gitea:** Lightweight Git service (this repository is hosted on it!).
|
||||
- **Gitea runner:** A runner for Gitea actions.
|
||||
- **Actual Budget:** Local-first personal finance app.
|
||||
|
||||
---
|
||||
|
||||
### Usage
|
||||
|
||||
This repository is not intended for direct cloning and deployment as-is. It is highly tailored to my specific setup, including domain names (bouvais.lu), paths, and personal configurations.
|
||||
However, you can use this repository as an example or reference.
|
89
compose-apps.yml
Normal file
@ -0,0 +1,89 @@
|
||||
services:
|
||||
memos:
|
||||
image: neosmemo/memos:stable
|
||||
container_name: memos
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- "./hdd0/memos:/var/opt/memos"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.memos.rule=Host(`notes.bouvais.lu`)"
|
||||
- "traefik.http.routers.memos.entrypoints=websecure"
|
||||
- "traefik.http.routers.memos.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.memos.loadbalancer.server.port=5230"
|
||||
|
||||
jellyfin:
|
||||
image: jellyfin/jellyfin
|
||||
container_name: jellyfin
|
||||
restart: unless-stopped
|
||||
group_add:
|
||||
- '107' #render
|
||||
- '44' #video
|
||||
volumes:
|
||||
- "./cache/jellyfin:/cache"
|
||||
- "./hdd0/jellyfin:/config"
|
||||
- "./hdd0/media:/media"
|
||||
- type: bind
|
||||
source: /data/media
|
||||
target: /media
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.jellyfin.rule=Host(`jellyfin.bouvais.lu`)"
|
||||
- "traefik.http.routers.jellyfin.entrypoints=websecure"
|
||||
- "traefik.http.routers.jellyfin.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
|
||||
|
||||
filebrowser:
|
||||
image: filebrowser/filebrowser:latest
|
||||
container_name: filebrowser
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
TZ: Europe/Luxembourg
|
||||
FB_BASEURL: /
|
||||
volumes:
|
||||
- "./config/filebrowser/filebrowser.json:/.filebrowser.json"
|
||||
- "./hdd0/filebrowser/filebrowser.db:/database.db"
|
||||
- "./hdd0/my_files:/srv"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.filebrowser.rule=Host(`files.bouvais.lu`)"
|
||||
- "traefik.http.routers.filebrowser.entrypoints=websecure"
|
||||
- "traefik.http.routers.filebrowser.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.filebrowser.loadbalancer.server.port=80"
|
||||
|
||||
actualbudget:
|
||||
image: actualbudget/actual-server:latest
|
||||
container_name: actualbudget
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- "./hdd0/actualbudget:/data"
|
||||
environment:
|
||||
- TZ=Europe/Luxembourg
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.actualbudget.rule=Host(`budget.bouvais.lu`)"
|
||||
- "traefik.http.routers.actualbudget.entrypoints=websecure"
|
||||
- "traefik.http.routers.actualbudget.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.actualbudget.loadbalancer.server.port=5006"
|
||||
|
||||
vaultwarden:
|
||||
image: vaultwarden/server:1.33.2
|
||||
container_name: vaultwarden
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
DOMAIN: "https://vault.bouvais.lu"
|
||||
SIGNUPS_ALLOWED: false
|
||||
volumes:
|
||||
- "./hdd0/vaultwarden:/data/"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.services.my-vaultwarden-service.loadbalancer.server.port=80"
|
||||
- "traefik.http.routers.vaultwarden.rule=Host(`vault.bouvais.lu`)"
|
||||
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
|
||||
- "traefik.http.routers.vaultwarden.tls.certresolver=myresolver"
|
||||
- "traefik.http.routers.vaultwarden.service=my-vaultwarden-service@docker"
|
||||
- "traefik.http.routers.vaultwarden-admin.rule=Host(`vault.bouvais.lu`) && PathPrefix(`/admin`)"
|
||||
- "traefik.http.routers.vaultwarden-admin.entrypoints=websecure"
|
||||
- "traefik.http.routers.vaultwarden-admin.tls.certresolver=myresolver"
|
||||
- "traefik.http.routers.vaultwarden-admin.middlewares=auth@docker"
|
||||
- "traefik.http.routers.vaultwarden-admin.service=my-vaultwarden-service@docker"
|
47
compose-gitea.yml
Normal file
@ -0,0 +1,47 @@
|
||||
services:
|
||||
gitea:
|
||||
image: "docker.gitea.com/gitea:1.23.8"
|
||||
container_name: gitea
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- GITEA_CUSTOM=/etc/gitea
|
||||
volumes:
|
||||
- "./hdd0/gitea:/data"
|
||||
- "./config/gitea:/etc/gitea"
|
||||
- "/etc/timezone:/etc/timezone:ro"
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# HTTP/S
|
||||
- "traefik.http.routers.gitea.rule=Host(`git.bouvais.lu`)"
|
||||
- "traefik.http.routers.gitea.entrypoints=websecure"
|
||||
- "traefik.http.routers.gitea.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
|
||||
# SSH
|
||||
- "traefik.tcp.routers.gitea-ssh.rule=HostSNI(`*`)"
|
||||
- "traefik.tcp.routers.gitea-ssh.entrypoints=ssh"
|
||||
- "traefik.tcp.services.gitea-ssh.loadbalancer.server.port=22"
|
||||
|
||||
gitea-runner:
|
||||
image: docker.io/gitea/act_runner:latest
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
CONFIG_FILE: /config.yaml
|
||||
GITEA_INSTANCE_URL: http://gitea:3000
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: m03Cj8wJjujfRXenMoN0pVy1J34GmuwbZZ9Bghs1
|
||||
volumes:
|
||||
- ./config/gitea-runner/config.yaml:/config.yaml
|
||||
- ./hdd0/gitea-runner:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
mkdocs:
|
||||
image: squidfunk/mkdocs-material
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./:/docs
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.gitea.rule=Host(`git.bouvais.lu`)"
|
||||
- "traefik.http.routers.gitea.entrypoints=websecure"
|
||||
- "traefik.http.routers.gitea.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
|
81
compose-monitoring.yml
Normal file
@ -0,0 +1,81 @@
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus:v3.4.0
|
||||
container_name: prometheus
|
||||
privileged: true
|
||||
user: root
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./config/prometheus:/etc/prometheus
|
||||
- ./hdd0/prometheus:/prometheus # For Prometheus data persistence
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
- '--storage.tsdb.path=/prometheus'
|
||||
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
|
||||
- '--web.console.templates=/usr/share/prometheus/consoles'
|
||||
- '--web.enable-lifecycle' # Allows hot-reloading of config via API
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.prometheus.rule=Host(`prometheus.bouvais.lu`)"
|
||||
- "traefik.http.routers.prometheus.entrypoints=websecure"
|
||||
- "traefik.http.routers.prometheus.tls.certresolver=myresolver"
|
||||
- "traefik.http.routers.prometheus.service=prometheus"
|
||||
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
|
||||
- "traefik.http.routers.prometheus.middlewares=auth@docker"
|
||||
depends_on:
|
||||
- cadvisor
|
||||
- node-exporter
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:12.0.1
|
||||
container_name: grafana
|
||||
privileged: true
|
||||
user: root
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./hdd0/grafana:/var/lib/grafana
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=adrien
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_MY_PASSWORD}
|
||||
- GF_SERVER_ROOT_URL=https://grafana.bouvais.lu # Set this for correct links if behind a subpath
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.grafana.rule=Host(`grafana.bouvais.lu`)"
|
||||
- "traefik.http.routers.grafana.entrypoints=websecure"
|
||||
- "traefik.http.routers.grafana.tls.certresolver=myresolver"
|
||||
- "traefik.http.routers.grafana.service=grafana"
|
||||
- "traefik.http.services.grafana.loadbalancer.server.port=3000" # Grafana's default port
|
||||
- "traefik.http.routers.grafana.middlewares=auth@docker"
|
||||
depends_on:
|
||||
- prometheus
|
||||
|
||||
cadvisor:
|
||||
image: gcr.io/cadvisor/cadvisor:v0.52.0
|
||||
container_name: cadvisor
|
||||
privileged: true
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /:/rootfs:ro
|
||||
- /var/run:/var/run:rw
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker/:/var/lib/docker:ro
|
||||
- /dev/disk/:/dev/disk:ro
|
||||
devices:
|
||||
- /dev/kmsg:/dev/kmsg
|
||||
|
||||
node-exporter:
|
||||
image: prom/node-exporter:v1.9.1
|
||||
container_name: node-exporter
|
||||
privileged: true
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /:/rootfs:ro
|
||||
command:
|
||||
- '--path.procfs=/host/proc'
|
||||
- '--path.sysfs=/host/sys'
|
||||
- '--path.rootfs=/rootfs'
|
||||
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)'
|
||||
|
||||
|
13
compose-website.yml
Normal file
@ -0,0 +1,13 @@
|
||||
services:
|
||||
website-pro:
|
||||
build:
|
||||
context: ./website-pro
|
||||
dockerfile: Dockerfile
|
||||
container_name: website-pro
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.www.rule=Host(`www.bouvais.lu`)"
|
||||
- "traefik.http.routers.www.entrypoints=websecure"
|
||||
- "traefik.http.routers.www.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.www.loadbalancer.server.port=8080"
|
8
config/filebrowser/filebrowser.json
Executable file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"port": 80,
|
||||
"baseURL": "files.bouvais.lu",
|
||||
"address": "0.0.0.0",
|
||||
"log": "stdout",
|
||||
"database": "/database.db",
|
||||
"root": "/srv"
|
||||
}
|
0
config/gitea-runner/config.yaml
Normal file
1
config/gitea/public/assets/css/theme-auto.css
Normal file
@ -0,0 +1 @@
|
||||
@import "./theme-light.css"(prefers-color-scheme:light);@import "./theme-dark.css"(prefers-color-scheme:dark);
|
1
config/gitea/public/assets/css/theme-dark.css
Normal file
1
config/gitea/public/assets/css/theme-light.css
Normal file
23
config/gitea/public/assets/img/favicon.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
|
||||
<desc>Created with Fabric.js 5.2.4</desc>
|
||||
<defs>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="transparent"></rect>
|
||||
<g transform="matrix(1 0 0 1 540 540)" id="b1285610-dc32-45a8-9642-309fa9224800" >
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 540 540)" id="50e8875c-2da2-4b35-a893-820abf496ce1" >
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x="-540" y="-540" rx="0" ry="0" width="1080" height="1080" />
|
||||
</g>
|
||||
<g transform="matrix(1.05 0 0 1.05 521.54 520.51)" >
|
||||
<g style="" >
|
||||
<g transform="matrix(0.13 0 0 -0.13 16 19.46)" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-5240, -4974.05)" d="M 4830 7934 C 4287 7884 3837 7672 3364 7244 C 3031 6942 2707 6614 2600 6470 C 2469 6294 2448 6129 2534 5954 C 2577 5869 2620 5808 2763 5637 C 2883 5493 2900 5466 2900 5417 C 2900 5398 2875 5293 2845 5184 C 2655 4500 2380 3719 2213 3391 L 2160 3286 L 2203 3246 C 2319 3135 2648 2907 2909 2755 C 3094 2648 3452 2475 3650 2396 C 4174 2190 4722 2060 5244 2019 C 5434 2004 5904 2013 6055 2034 C 6280 2066 6360 2091 6360 2129 C 6360 2139 6311 2307 6251 2501 C 6130 2894 6085 3062 6041 3285 C 5924 3878 5944 4227 6104 4368 C 6156 4413 6206 4424 6340 4416 C 6745 4394 6899 4399 7126 4445 C 7595 4540 7921 4826 8130 5328 C 8254 5624 8320 5903 8320 6131 C 8320 6224 8317 6242 8295 6287 C 8238 6400 8159 6434 7589 6585 C 7103 6715 6952 6770 6851 6856 C 6808 6893 6732 7003 6710 7060 C 6651 7213 6432 7486 6266 7613 C 6022 7801 5830 7872 5450 7915 C 5319 7930 4922 7942 4830 7934 z M 5411 7620 C 5624 7598 5828 7543 5936 7479 C 6010 7435 6160 7292 6254 7176 C 6295 7126 6358 7031 6395 6965 C 6479 6814 6512 6769 6600 6687 C 6716 6577 6880 6508 7333 6376 C 7437 6346 7524 6319 7527 6316 C 7530 6313 7517 6269 7499 6218 C 7437 6049 7455 5924 7558 5810 C 7611 5750 7677 5715 7786 5690 C 7835 5679 7880 5663 7886 5654 C 7895 5643 7895 5624 7884 5577 C 7811 5263 7554 4954 7260 4829 C 7068 4748 6884 4724 6545 4736 C 6413 4741 6222 4744 6120 4743 C 5960 4742 5923 4738 5843 4717 C 5606 4655 5415 4459 5326 4188 C 5280 4047 5267 3928 5273 3721 C 5279 3514 5301 3387 5366 3180 C 5439 2945 5512 2788 5669 2526 C 5725 2433 5770 2355 5770 2352 C 5770 2342 5240 2359 5110 2374 C 4626 2430 4225 2531 3750 2717 C 3540 2799 3191 2971 2986 3094 C 2823 3192 2601 3346 2593 3366 C 2591 3372 2620 3456 2659 3552 C 2810 3931 3035 4602 3175 5093 C 3184 5124 3195 5150 3199 5150 C 3204 5150 3252 5109 3306 5058 C 3455 4921 3531 4857 3616 4799 C 3860 4634 4076 4590 4245 4668 C 4405 4743 4492 4901 4521 5169 C 4549 5427 4509 6177 4420 7070 C 4410 7177 4398 7318 4394 7382 L 4387 7500 L 4442 7525 C 4530 7565 4678 7592 4980 7623 C 5060 7631 5315 7629 5411 7620 z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(0.13 0 0 -0.13 92.12 -201.19)" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-5810.87, -6628.95)" d="M 5769 6889 C 5710 6880 5674 6861 5629 6813 C 5519 6698 5516 6537 5621 6432 C 5672 6380 5707 6366 5780 6366 C 5953 6366 6098 6526 6075 6692 C 6058 6814 5909 6910 5769 6889 z" stroke-linecap="round" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
BIN
config/gitea/public/assets/img/logo.png
Normal file
After Width: | Height: | Size: 74 KiB |
23
config/gitea/public/assets/img/logo.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
|
||||
<desc>Created with Fabric.js 5.2.4</desc>
|
||||
<defs>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="transparent"></rect>
|
||||
<g transform="matrix(1 0 0 1 540 540)" id="b1285610-dc32-45a8-9642-309fa9224800" >
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 540 540)" id="50e8875c-2da2-4b35-a893-820abf496ce1" >
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x="-540" y="-540" rx="0" ry="0" width="1080" height="1080" />
|
||||
</g>
|
||||
<g transform="matrix(1.05 0 0 1.05 521.54 520.51)" >
|
||||
<g style="" >
|
||||
<g transform="matrix(0.13 0 0 -0.13 16 19.46)" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-5240, -4974.05)" d="M 4830 7934 C 4287 7884 3837 7672 3364 7244 C 3031 6942 2707 6614 2600 6470 C 2469 6294 2448 6129 2534 5954 C 2577 5869 2620 5808 2763 5637 C 2883 5493 2900 5466 2900 5417 C 2900 5398 2875 5293 2845 5184 C 2655 4500 2380 3719 2213 3391 L 2160 3286 L 2203 3246 C 2319 3135 2648 2907 2909 2755 C 3094 2648 3452 2475 3650 2396 C 4174 2190 4722 2060 5244 2019 C 5434 2004 5904 2013 6055 2034 C 6280 2066 6360 2091 6360 2129 C 6360 2139 6311 2307 6251 2501 C 6130 2894 6085 3062 6041 3285 C 5924 3878 5944 4227 6104 4368 C 6156 4413 6206 4424 6340 4416 C 6745 4394 6899 4399 7126 4445 C 7595 4540 7921 4826 8130 5328 C 8254 5624 8320 5903 8320 6131 C 8320 6224 8317 6242 8295 6287 C 8238 6400 8159 6434 7589 6585 C 7103 6715 6952 6770 6851 6856 C 6808 6893 6732 7003 6710 7060 C 6651 7213 6432 7486 6266 7613 C 6022 7801 5830 7872 5450 7915 C 5319 7930 4922 7942 4830 7934 z M 5411 7620 C 5624 7598 5828 7543 5936 7479 C 6010 7435 6160 7292 6254 7176 C 6295 7126 6358 7031 6395 6965 C 6479 6814 6512 6769 6600 6687 C 6716 6577 6880 6508 7333 6376 C 7437 6346 7524 6319 7527 6316 C 7530 6313 7517 6269 7499 6218 C 7437 6049 7455 5924 7558 5810 C 7611 5750 7677 5715 7786 5690 C 7835 5679 7880 5663 7886 5654 C 7895 5643 7895 5624 7884 5577 C 7811 5263 7554 4954 7260 4829 C 7068 4748 6884 4724 6545 4736 C 6413 4741 6222 4744 6120 4743 C 5960 4742 5923 4738 5843 4717 C 5606 4655 5415 4459 5326 4188 C 5280 4047 5267 3928 5273 3721 C 5279 3514 5301 3387 5366 3180 C 5439 2945 5512 2788 5669 2526 C 5725 2433 5770 2355 5770 2352 C 5770 2342 5240 2359 5110 2374 C 4626 2430 4225 2531 3750 2717 C 3540 2799 3191 2971 2986 3094 C 2823 3192 2601 3346 2593 3366 C 2591 3372 2620 3456 2659 3552 C 2810 3931 3035 4602 3175 5093 C 3184 5124 3195 5150 3199 5150 C 3204 5150 3252 5109 3306 5058 C 3455 4921 3531 4857 3616 4799 C 3860 4634 4076 4590 4245 4668 C 4405 4743 4492 4901 4521 5169 C 4549 5427 4509 6177 4420 7070 C 4410 7177 4398 7318 4394 7382 L 4387 7500 L 4442 7525 C 4530 7565 4678 7592 4980 7623 C 5060 7631 5315 7629 5411 7620 z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(0.13 0 0 -0.13 92.12 -201.19)" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-5810.87, -6628.95)" d="M 5769 6889 C 5710 6880 5674 6861 5629 6813 C 5519 6698 5516 6537 5621 6432 C 5672 6380 5707 6366 5780 6366 C 5953 6366 6098 6526 6075 6692 C 6058 6814 5909 6910 5769 6889 z" stroke-linecap="round" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
BIN
config/gitea/public/assets/img/logo_dark.png
Normal file
After Width: | Height: | Size: 69 KiB |
22
config/gitea/public/assets/img/logo_dark.svg
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
|
||||
<desc>Created with Fabric.js 5.2.4</desc>
|
||||
<defs>
|
||||
</defs>
|
||||
<g transform="matrix(1 0 0 1 540 540)" id="b1285610-dc32-45a8-9642-309fa9224800" >
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 540 540)" id="50e8875c-2da2-4b35-a893-820abf496ce1" >
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x="-540" y="-540" rx="0" ry="0" width="1080" height="1080" />
|
||||
</g>
|
||||
<g transform="matrix(1.05 0 0 1.05 521.54 520.51)" >
|
||||
<g style="" >
|
||||
<g transform="matrix(0.13 0 0 -0.13 16 19.46)" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-5240, -4974.05)" d="M 4830 7934 C 4287 7884 3837 7672 3364 7244 C 3031 6942 2707 6614 2600 6470 C 2469 6294 2448 6129 2534 5954 C 2577 5869 2620 5808 2763 5637 C 2883 5493 2900 5466 2900 5417 C 2900 5398 2875 5293 2845 5184 C 2655 4500 2380 3719 2213 3391 L 2160 3286 L 2203 3246 C 2319 3135 2648 2907 2909 2755 C 3094 2648 3452 2475 3650 2396 C 4174 2190 4722 2060 5244 2019 C 5434 2004 5904 2013 6055 2034 C 6280 2066 6360 2091 6360 2129 C 6360 2139 6311 2307 6251 2501 C 6130 2894 6085 3062 6041 3285 C 5924 3878 5944 4227 6104 4368 C 6156 4413 6206 4424 6340 4416 C 6745 4394 6899 4399 7126 4445 C 7595 4540 7921 4826 8130 5328 C 8254 5624 8320 5903 8320 6131 C 8320 6224 8317 6242 8295 6287 C 8238 6400 8159 6434 7589 6585 C 7103 6715 6952 6770 6851 6856 C 6808 6893 6732 7003 6710 7060 C 6651 7213 6432 7486 6266 7613 C 6022 7801 5830 7872 5450 7915 C 5319 7930 4922 7942 4830 7934 z M 5411 7620 C 5624 7598 5828 7543 5936 7479 C 6010 7435 6160 7292 6254 7176 C 6295 7126 6358 7031 6395 6965 C 6479 6814 6512 6769 6600 6687 C 6716 6577 6880 6508 7333 6376 C 7437 6346 7524 6319 7527 6316 C 7530 6313 7517 6269 7499 6218 C 7437 6049 7455 5924 7558 5810 C 7611 5750 7677 5715 7786 5690 C 7835 5679 7880 5663 7886 5654 C 7895 5643 7895 5624 7884 5577 C 7811 5263 7554 4954 7260 4829 C 7068 4748 6884 4724 6545 4736 C 6413 4741 6222 4744 6120 4743 C 5960 4742 5923 4738 5843 4717 C 5606 4655 5415 4459 5326 4188 C 5280 4047 5267 3928 5273 3721 C 5279 3514 5301 3387 5366 3180 C 5439 2945 5512 2788 5669 2526 C 5725 2433 5770 2355 5770 2352 C 5770 2342 5240 2359 5110 2374 C 4626 2430 4225 2531 3750 2717 C 3540 2799 3191 2971 2986 3094 C 2823 3192 2601 3346 2593 3366 C 2591 3372 2620 3456 2659 3552 C 2810 3931 3035 4602 3175 5093 C 3184 5124 3195 5150 3199 5150 C 3204 5150 3252 5109 3306 5058 C 3455 4921 3531 4857 3616 4799 C 3860 4634 4076 4590 4245 4668 C 4405 4743 4492 4901 4521 5169 C 4549 5427 4509 6177 4420 7070 C 4410 7177 4398 7318 4394 7382 L 4387 7500 L 4442 7525 C 4530 7565 4678 7592 4980 7623 C 5060 7631 5315 7629 5411 7620 z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(0.13 0 0 -0.13 92.12 -201.19)" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-5810.87, -6628.95)" d="M 5769 6889 C 5710 6880 5674 6861 5629 6813 C 5519 6698 5516 6537 5621 6432 C 5672 6380 5707 6366 5780 6366 C 5953 6366 6098 6526 6075 6692 C 6058 6814 5909 6910 5769 6889 z" stroke-linecap="round" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
BIN
config/gitea/public/assets/img/logo_light.png
Normal file
After Width: | Height: | Size: 74 KiB |
23
config/gitea/public/assets/img/logo_light.svg
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
|
||||
<desc>Created with Fabric.js 5.2.4</desc>
|
||||
<defs>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="100%" height="100%" fill="transparent"></rect>
|
||||
<g transform="matrix(1 0 0 1 540 540)" id="b1285610-dc32-45a8-9642-309fa9224800" >
|
||||
</g>
|
||||
<g transform="matrix(1 0 0 1 540 540)" id="50e8875c-2da2-4b35-a893-820abf496ce1" >
|
||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x="-540" y="-540" rx="0" ry="0" width="1080" height="1080" />
|
||||
</g>
|
||||
<g transform="matrix(1.05 0 0 1.05 521.54 520.51)" >
|
||||
<g style="" >
|
||||
<g transform="matrix(0.13 0 0 -0.13 16 19.46)" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-5240, -4974.05)" d="M 4830 7934 C 4287 7884 3837 7672 3364 7244 C 3031 6942 2707 6614 2600 6470 C 2469 6294 2448 6129 2534 5954 C 2577 5869 2620 5808 2763 5637 C 2883 5493 2900 5466 2900 5417 C 2900 5398 2875 5293 2845 5184 C 2655 4500 2380 3719 2213 3391 L 2160 3286 L 2203 3246 C 2319 3135 2648 2907 2909 2755 C 3094 2648 3452 2475 3650 2396 C 4174 2190 4722 2060 5244 2019 C 5434 2004 5904 2013 6055 2034 C 6280 2066 6360 2091 6360 2129 C 6360 2139 6311 2307 6251 2501 C 6130 2894 6085 3062 6041 3285 C 5924 3878 5944 4227 6104 4368 C 6156 4413 6206 4424 6340 4416 C 6745 4394 6899 4399 7126 4445 C 7595 4540 7921 4826 8130 5328 C 8254 5624 8320 5903 8320 6131 C 8320 6224 8317 6242 8295 6287 C 8238 6400 8159 6434 7589 6585 C 7103 6715 6952 6770 6851 6856 C 6808 6893 6732 7003 6710 7060 C 6651 7213 6432 7486 6266 7613 C 6022 7801 5830 7872 5450 7915 C 5319 7930 4922 7942 4830 7934 z M 5411 7620 C 5624 7598 5828 7543 5936 7479 C 6010 7435 6160 7292 6254 7176 C 6295 7126 6358 7031 6395 6965 C 6479 6814 6512 6769 6600 6687 C 6716 6577 6880 6508 7333 6376 C 7437 6346 7524 6319 7527 6316 C 7530 6313 7517 6269 7499 6218 C 7437 6049 7455 5924 7558 5810 C 7611 5750 7677 5715 7786 5690 C 7835 5679 7880 5663 7886 5654 C 7895 5643 7895 5624 7884 5577 C 7811 5263 7554 4954 7260 4829 C 7068 4748 6884 4724 6545 4736 C 6413 4741 6222 4744 6120 4743 C 5960 4742 5923 4738 5843 4717 C 5606 4655 5415 4459 5326 4188 C 5280 4047 5267 3928 5273 3721 C 5279 3514 5301 3387 5366 3180 C 5439 2945 5512 2788 5669 2526 C 5725 2433 5770 2355 5770 2352 C 5770 2342 5240 2359 5110 2374 C 4626 2430 4225 2531 3750 2717 C 3540 2799 3191 2971 2986 3094 C 2823 3192 2601 3346 2593 3366 C 2591 3372 2620 3456 2659 3552 C 2810 3931 3035 4602 3175 5093 C 3184 5124 3195 5150 3199 5150 C 3204 5150 3252 5109 3306 5058 C 3455 4921 3531 4857 3616 4799 C 3860 4634 4076 4590 4245 4668 C 4405 4743 4492 4901 4521 5169 C 4549 5427 4509 6177 4420 7070 C 4410 7177 4398 7318 4394 7382 L 4387 7500 L 4442 7525 C 4530 7565 4678 7592 4980 7623 C 5060 7631 5315 7629 5411 7620 z" stroke-linecap="round" />
|
||||
</g>
|
||||
<g transform="matrix(0.13 0 0 -0.13 92.12 -201.19)" >
|
||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-5810.87, -6628.95)" d="M 5769 6889 C 5710 6880 5674 6861 5629 6813 C 5519 6698 5516 6537 5621 6432 C 5672 6380 5707 6366 5780 6366 C 5953 6366 6098 6526 6075 6692 C 6058 6814 5909 6910 5769 6889 z" stroke-linecap="round" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
34
config/gitea/templates/base/footer.tmpl
Normal file
@ -0,0 +1,34 @@
|
||||
{{if false}}
|
||||
{{/* to make html structure "likely" complete to prevent IDE warnings */}}
|
||||
<html>
|
||||
<body>
|
||||
<div>
|
||||
{{end}}
|
||||
|
||||
<script src="{{AssetUrlPrefix}}/js/index.js?v={{AssetVersion}}" onerror="alert('Failed to load asset files from ' + this.src + '. Please make sure the asset files can be accessed.')"></script>
|
||||
|
||||
<script>
|
||||
const dynamicLogo = document.getElementById('dynamic-logo');
|
||||
const assetUrlPrefix = "{{AssetUrlPrefix}}"; // Get the asset URL prefix from your Go template
|
||||
|
||||
function setLogoBasedOnTheme() {
|
||||
if (getComputedStyle(document.documentElement).getPropertyValue('--is-dark-theme').trim() == 'true') {
|
||||
// Dark mode is active
|
||||
dynamicLogo.src = `${assetUrlPrefix}/img/logo_light.svg`;
|
||||
} else {
|
||||
// Light mode or no preference (default to light)
|
||||
dynamicLogo.src = `${assetUrlPrefix}/img/logo_dark.svg`;
|
||||
}
|
||||
}
|
||||
|
||||
// Set logo on initial load
|
||||
setLogoBasedOnTheme();
|
||||
|
||||
// Listen for changes in the color scheme
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
||||
setLogoBasedOnTheme();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
214
config/gitea/templates/base/head_navbar.tmpl
Normal file
@ -0,0 +1,214 @@
|
||||
{{$notificationUnreadCount := 0}}
|
||||
{{if and .IsSigned .NotificationUnreadCount}}
|
||||
{{$notificationUnreadCount = call .NotificationUnreadCount}}
|
||||
{{end}}
|
||||
|
||||
<nav id="navbar" aria-label="{{ctx.Locale.Tr "aria.navbar"}}">
|
||||
<div class="navbar-left">
|
||||
<!-- the logo -->
|
||||
<a class="item" id="navbar-logo" href="{{AppSubUrl}}/" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}">
|
||||
<img id="dynamic-logo" width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true">
|
||||
</a>
|
||||
|
||||
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
|
||||
<div class="ui secondary menu navbar-mobile-right only-mobile">
|
||||
{{if and .IsSigned EnableTimetracking .ActiveStopwatch}}
|
||||
<a id="mobile-stopwatch-icon" class="active-stopwatch item tw-mx-0" href="{{.ActiveStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{.ActiveStopwatch.Seconds}}">
|
||||
<div class="tw-relative">
|
||||
{{svg "octicon-stopwatch"}}
|
||||
<span class="header-stopwatch-dot"></span>
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .IsSigned}}
|
||||
<a id="mobile-notifications-icon" class="item tw-w-auto tw-p-2" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}">
|
||||
<div class="tw-relative">
|
||||
{{svg "octicon-bell"}}
|
||||
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
<button class="item tw-w-auto ui icon mini button tw-p-2 tw-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "home.nav_menu"}}">{{svg "octicon-three-bars"}}</button>
|
||||
</div>
|
||||
|
||||
<!-- navbar links non-mobile -->
|
||||
{{if and .IsSigned .MustChangePassword}}
|
||||
{{/* No links */}}
|
||||
{{else if .IsSigned}}
|
||||
{{if not ctx.Consts.RepoUnitTypeIssues.UnitGlobalDisabled}}
|
||||
<a class="item{{if .PageIsIssues}} active{{end}}" href="{{AppSubUrl}}/issues">{{ctx.Locale.Tr "issues"}}</a>
|
||||
{{end}}
|
||||
{{if not ctx.Consts.RepoUnitTypePullRequests.UnitGlobalDisabled}}
|
||||
<a class="item{{if .PageIsPulls}} active{{end}}" href="{{AppSubUrl}}/pulls">{{ctx.Locale.Tr "pull_requests"}}</a>
|
||||
{{end}}
|
||||
{{if not (and ctx.Consts.RepoUnitTypeIssues.UnitGlobalDisabled ctx.Consts.RepoUnitTypePullRequests.UnitGlobalDisabled)}}
|
||||
{{if .ShowMilestonesDashboardPage}}
|
||||
<a class="item{{if .PageIsMilestonesDashboard}} active{{end}}" href="{{AppSubUrl}}/milestones">{{ctx.Locale.Tr "milestones"}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a>
|
||||
{{else if .IsLandingPageOrganizations}}
|
||||
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{ctx.Locale.Tr "explore"}}</a>
|
||||
{{else}}
|
||||
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a>
|
||||
{{end}}
|
||||
|
||||
{{template "custom/extra_links" .}}
|
||||
|
||||
{{if not .IsSigned}}
|
||||
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">{{ctx.Locale.Tr "help"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<!-- the full dropdown menus -->
|
||||
<div class="navbar-right">
|
||||
{{if and .IsSigned .MustChangePassword}}
|
||||
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
|
||||
<span class="text tw-flex tw-items-center">
|
||||
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
|
||||
<span class="only-mobile tw-ml-2">{{.SignedUser.Name}}</span>
|
||||
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
|
||||
</span>
|
||||
<div class="menu user-menu">
|
||||
<div class="header">
|
||||
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
|
||||
{{svg "octicon-sign-out"}}
|
||||
{{ctx.Locale.Tr "sign_out"}}
|
||||
</a>
|
||||
</div><!-- end content avatar menu -->
|
||||
</div><!-- end dropdown avatar menu -->
|
||||
{{else if .IsSigned}}
|
||||
{{if and EnableTimetracking .ActiveStopwatch}}
|
||||
<a class="item not-mobile active-stopwatch tw-mx-0" href="{{.ActiveStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}" data-seconds="{{.ActiveStopwatch.Seconds}}">
|
||||
<div class="tw-relative">
|
||||
{{svg "octicon-stopwatch"}}
|
||||
<span class="header-stopwatch-dot"></span>
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
<a class="item not-mobile tw-mx-0" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}">
|
||||
<div class="tw-relative">
|
||||
{{svg "octicon-bell"}}
|
||||
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="ui dropdown jump item tw-mx-0 tw-pr-2" data-tooltip-content="{{ctx.Locale.Tr "create_new"}}">
|
||||
<span class="text">
|
||||
{{svg "octicon-plus"}}
|
||||
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
|
||||
<span class="only-mobile">{{ctx.Locale.Tr "create_new"}}</span>
|
||||
</span>
|
||||
<div class="menu">
|
||||
<a class="item" href="{{AppSubUrl}}/repo/create">
|
||||
{{svg "octicon-plus"}} {{ctx.Locale.Tr "new_repo"}}
|
||||
</a>
|
||||
{{if not .DisableMigrations}}
|
||||
<a class="item" href="{{AppSubUrl}}/repo/migrate">
|
||||
{{svg "octicon-repo-push"}} {{ctx.Locale.Tr "new_migrate"}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{if .SignedUser.CanCreateOrganization}}
|
||||
<a class="item" href="{{AppSubUrl}}/org/create">
|
||||
{{svg "octicon-organization"}} {{ctx.Locale.Tr "new_org"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div><!-- end content create new menu -->
|
||||
</div><!-- end dropdown menu create new -->
|
||||
|
||||
<div class="ui dropdown jump item tw-mx-0 tw-pr-2" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
|
||||
<span class="text tw-flex tw-items-center">
|
||||
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
|
||||
<span class="only-mobile tw-ml-2">{{.SignedUser.Name}}</span>
|
||||
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
|
||||
</span>
|
||||
<div class="menu user-menu">
|
||||
<div class="header">
|
||||
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<a class="item" href="{{.SignedUser.HomeLink}}">
|
||||
{{svg "octicon-person"}}
|
||||
{{ctx.Locale.Tr "your_profile"}}
|
||||
</a>
|
||||
{{if not .DisableStars}}
|
||||
<a class="item" href="{{.SignedUser.HomeLink}}?tab=stars">
|
||||
{{svg "octicon-star"}}
|
||||
{{ctx.Locale.Tr "your_starred"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="item" href="{{AppSubUrl}}/notifications/subscriptions">
|
||||
{{svg "octicon-bell"}}
|
||||
{{ctx.Locale.Tr "notification.subscriptions"}}
|
||||
</a>
|
||||
<a class="{{if .PageIsUserSettings}}active {{end}}item" href="{{AppSubUrl}}/user/settings">
|
||||
{{svg "octicon-tools"}}
|
||||
{{ctx.Locale.Tr "your_settings"}}
|
||||
</a>
|
||||
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">
|
||||
{{svg "octicon-question"}}
|
||||
{{ctx.Locale.Tr "help"}}
|
||||
</a>
|
||||
{{if .IsAdmin}}
|
||||
<div class="divider"></div>
|
||||
|
||||
<a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/-/admin">
|
||||
{{svg "octicon-server"}}
|
||||
{{ctx.Locale.Tr "admin_panel"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
||||
<div class="divider"></div>
|
||||
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
|
||||
{{svg "octicon-sign-out"}}
|
||||
{{ctx.Locale.Tr "sign_out"}}
|
||||
</a>
|
||||
</div><!-- end content avatar menu -->
|
||||
</div><!-- end dropdown avatar menu -->
|
||||
{{else}}
|
||||
{{if .ShowRegistrationButton}}
|
||||
<a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up">
|
||||
{{svg "octicon-person"}} {{ctx.Locale.Tr "register"}}
|
||||
</a>
|
||||
{{end}}
|
||||
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login{{if not .PageIsSignIn}}?redirect_to={{.CurrentURL}}{{end}}">
|
||||
{{svg "octicon-sign-in"}} {{ctx.Locale.Tr "sign_in"}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div><!-- end full right menu -->
|
||||
|
||||
{{if and .IsSigned EnableTimetracking .ActiveStopwatch}}
|
||||
<div class="active-stopwatch-popup tippy-target">
|
||||
<div class="tw-flex tw-items-center tw-gap-2 tw-p-3">
|
||||
<a class="stopwatch-link tw-flex tw-items-center tw-gap-2 muted" href="{{.ActiveStopwatch.IssueLink}}">
|
||||
{{svg "octicon-issue-opened" 16}}
|
||||
<span class="stopwatch-issue">{{.ActiveStopwatch.RepoSlug}}#{{.ActiveStopwatch.IssueIndex}}</span>
|
||||
</a>
|
||||
<div class="tw-flex tw-gap-1">
|
||||
<form class="stopwatch-commit form-fetch-action" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/toggle">
|
||||
{{.CsrfTokenHtml}}
|
||||
<button
|
||||
type="submit"
|
||||
class="ui button mini compact basic icon tw-mr-0"
|
||||
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.stop_tracking"}}"
|
||||
>{{svg "octicon-square-fill"}}</button>
|
||||
</form>
|
||||
<form class="stopwatch-cancel form-fetch-action" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/cancel">
|
||||
{{.CsrfTokenHtml}}
|
||||
<button
|
||||
type="submit"
|
||||
class="ui button mini compact basic icon tw-mr-0"
|
||||
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.cancel_tracking"}}"
|
||||
>{{svg "octicon-trash"}}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</nav>
|
15
config/gitea/templates/home.tmpl
Normal file
@ -0,0 +1,15 @@
|
||||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}" class="page-content home">
|
||||
<div class="tw-mb-8 tw-px-8">
|
||||
<div class="center">
|
||||
<img class="logo" width="220" height="220" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}">
|
||||
<div class="hero">
|
||||
<h1 class="ui icon header title">
|
||||
{{AppName}}
|
||||
</h1>
|
||||
<h2>A simple place for my code.</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
20
config/kopia/repository.config
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"storage": {
|
||||
"type": "filesystem",
|
||||
"config": {
|
||||
"path": "/repository",
|
||||
"dirShards": null
|
||||
}
|
||||
},
|
||||
"caching": {
|
||||
"cacheDirectory": "../cache",
|
||||
"maxCacheSize": 5242880000,
|
||||
"maxMetadataCacheSize": 5242880000,
|
||||
"maxListCacheDuration": 30
|
||||
},
|
||||
"hostname": "b27568001edb",
|
||||
"username": "root",
|
||||
"description": "My Repository",
|
||||
"enableActions": false,
|
||||
"formatBlobCacheDuration": 900000000000
|
||||
}
|
0
config/kopia/repository.config.mlock
Normal file
1
config/kopia/ui-preferences.json
Normal file
@ -0,0 +1 @@
|
||||
{"bytesStringBase2":false,"defaultSnapshotViewAll":false,"theme":"dark","fontSize":"fs-6","pageSize":10,"language":""}
|
26
config/prometheus/prometheus.yml
Normal file
@ -0,0 +1,26 @@
|
||||
# ./prometheus/prometheus.yml
|
||||
|
||||
global:
|
||||
scrape_interval: 15s # Default scrape interval
|
||||
evaluation_interval: 15s # Default evaluation interval
|
||||
|
||||
scrape_configs:
|
||||
- job_name: 'traefik'
|
||||
static_configs:
|
||||
- targets: ['traefik:8080'] # This should match the port you set for metrics in Traefik's command
|
||||
|
||||
- job_name: 'prometheus'
|
||||
static_configs:
|
||||
- targets: ['localhost:9090']
|
||||
|
||||
- job_name: 'cadvisor' # For Docker container metrics
|
||||
static_configs:
|
||||
- targets: ['cadvisor:8080']
|
||||
|
||||
- job_name: 'node-exporter' # For host system metrics
|
||||
static_configs:
|
||||
- targets: ['node-exporter:9100']
|
||||
|
||||
- job_name: 'gitea' # For host system metrics
|
||||
static_configs:
|
||||
- targets: ['gitea:3000']
|
1
config/users.cred
Executable file
@ -0,0 +1 @@
|
||||
adrien:$apr1$jUYzh/ia$EBkIIA./9xR7gn0M3BsNs1
|
111
docker-compose.yml
Normal file
@ -0,0 +1,111 @@
|
||||
include:
|
||||
- compose-apps.yml
|
||||
- compose-gitea.yml
|
||||
- compose-monitoring.yml
|
||||
|
||||
services:
|
||||
traefik:
|
||||
image: "traefik:v3.4"
|
||||
container_name: "traefik"
|
||||
restart: unless-stopped
|
||||
command:
|
||||
# HTTPS TSL stuff
|
||||
- "--providers.docker=true"
|
||||
- "--providers.docker.exposedbydefault=false"
|
||||
- "--entryPoints.websecure.address=:443"
|
||||
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
|
||||
- "--certificatesresolvers.myresolver.acme.email=adrien.bouvais.pro@gmail.com"
|
||||
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" # Relative path on SSD
|
||||
# Enable Traefik API and Dashboard (securely)
|
||||
- "--api.dashboard=true"
|
||||
- "--metrics.prometheus=true"
|
||||
- "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0"
|
||||
- "--entryPoints.ssh.address=:2101"
|
||||
# Logs - Traefik will write its logs to /logs within the container, which maps to /data/logs on host
|
||||
- "--accesslog=true"
|
||||
- "--accesslog.format=json"
|
||||
- "--accesslog.filepath=/logs/access.log"
|
||||
- "--accesslog.bufferingSize=0"
|
||||
ports:
|
||||
- target: 443
|
||||
published: 443
|
||||
protocol: tcp
|
||||
mode: host
|
||||
- target: 2101
|
||||
published: 2101
|
||||
protocol: tcp
|
||||
mode: host
|
||||
volumes:
|
||||
- "./letsencrypt:/letsencrypt"
|
||||
- "/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
- "./config/users.cred:/users.cred"
|
||||
- "./hdd0/logs:/logs"
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
# Dashboard Router
|
||||
- "traefik.http.routers.dashboard.rule=Host(`traefik.bouvais.lu`)"
|
||||
- "traefik.http.routers.dashboard.entrypoints=websecure"
|
||||
- "traefik.http.routers.dashboard.service=api@internal"
|
||||
- "traefik.http.routers.dashboard.middlewares=auth@docker"
|
||||
- "traefik.http.routers.dashboard.tls.certresolver=myresolver"
|
||||
# Traefik Middleware
|
||||
- "traefik.http.middlewares.auth.basicauth.usersfile=/users.cred"
|
||||
- "traefik.http.middlewares.ratelimit.ratelimit.average=20"
|
||||
- "traefik.http.middlewares.ratelimit.ratelimit.burst=40"
|
||||
# bouvais.lu redirection
|
||||
- "traefik.http.routers.bouvais-redirect.rule=Host(`bouvais.lu`)"
|
||||
- "traefik.http.routers.bouvais-redirect.entrypoints=websecure"
|
||||
- "traefik.http.routers.bouvais-redirect.middlewares=redirect-to-gitea@docker"
|
||||
- "traefik.http.routers.bouvais-redirect.tls.certresolver=myresolver"
|
||||
- "traefik.http.middlewares.redirect-to-gitea.redirectregex.regex=^https?://(www\\.)?bouvais\\.lu(.*)"
|
||||
- "traefik.http.middlewares.redirect-to-gitea.redirectregex.replacement=https://git.bouvais.lu$${2}"
|
||||
- "traefik.http.middlewares.redirect-to-gitea.redirectregex.permanent=true"
|
||||
|
||||
fail2ban:
|
||||
image: crazymax/fail2ban:1.1.0
|
||||
container_name: fail2ban
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- NET_RAW
|
||||
network_mode: host
|
||||
volumes:
|
||||
- "./hdd0/fail2ban/data:/data"
|
||||
- "./hdd0/fail2ban/log:/var/log"
|
||||
- "./hdd0/logs:/logs:ro"
|
||||
- "/etc/localtime:/etc/localtime:ro"
|
||||
- "/etc/timezone:/etc/timezone:ro"
|
||||
environment:
|
||||
- F2B_IPTABLES_CHAIN=DOCKER-USER
|
||||
|
||||
kopia:
|
||||
image: kopia/kopia:latest
|
||||
container_name: kopia
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 51515:51515
|
||||
command:
|
||||
- server
|
||||
- start
|
||||
#- --disable-csrf-token-checks
|
||||
- --insecure
|
||||
- --address=0.0.0.0:51515
|
||||
- --server-username=adrien
|
||||
- --server-password=${MASTER_PASSWORD}
|
||||
environment:
|
||||
KOPIA_PASSWORD: ${MASTER_PASSWORD}
|
||||
USER: "adrien"
|
||||
volumes:
|
||||
# Mount local folders needed by kopia
|
||||
- ./config/kopia:/app/config
|
||||
- ./cache/kopia:/app/cache
|
||||
- ./hdd0/logs/:/app/logs
|
||||
- ./hdd0:/hdd0 # Mount local folders to snapshot
|
||||
- ./hdd0_backups/kopia/dir:/repository # Mount repository location
|
||||
- ./hdd0_backups/kopia/shared:/tmp:shared # Mount path for browsing mounted snaphots
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.kopia.rule=Host(`kopia.bouvais.lu`)"
|
||||
- "traefik.http.routers.kopia.entrypoints=websecure"
|
||||
- "traefik.http.routers.kopia.tls.certresolver=myresolver"
|
||||
- "traefik.http.services.kopia.loadbalancer.server.port=51515"
|