Initial commit

This commit is contained in:
Vloldik
2025-05-06 19:21:00 +03:00
commit 5f17ce5f03
28 changed files with 625 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
**/secrets/**
manifests/**/*secret.yaml
.gitattributes !filter !diff
!*.md

10
Readme.md Normal file
View File

@@ -0,0 +1,10 @@
# Инфраструктура сайта openvibes.ru
На данный момент на поддоменах развернуты сервисы:
- [git.openvibes.ru](./manifests/apps/gitea/helm/)
- [pm.openvibes.ru](./manifests/apps/planka/)
- [dbadmin.openvibes.ru](./manifests/apps/adminer/)
- [warden.openvibes.ru](./manifests/apps/vaultwarden/)
Как оркестратор используется k3s.

1
apps/smtprelay/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
smtprelay

32
apps/smtprelay/README.md Normal file
View File

@@ -0,0 +1,32 @@
# smtprelay
[![Go Report Card](https://goreportcard.com/badge/github.com/decke/smtprelay)](https://goreportcard.com/report/github.com/decke/smtprelay)
Simple Golang based SMTP relay/proxy server that accepts mail via SMTP
and forwards it directly to another SMTP server.
## Why another SMTP server?
Outgoing mails are usually send via SMTP to an MTA (Mail Transfer Agent)
which is one of Postfix, Exim, Sendmail or OpenSMTPD on UNIX/Linux in most
cases. You really don't want to setup and maintain any of those full blown
kitchensinks yourself because they are complex, fragile and hard to
configure.
My use case is simple. I need to send automatically generated mails from
cron via msmtp/sSMTP/dma, mails from various services and network printers
via a remote SMTP server without giving away my mail credentials to each
device which produces mail.
## Main features
* Simple configuration with ini file .env file or environment variables
* Supports SMTPS/TLS (465), STARTTLS (587) and unencrypted SMTP (25)
* Checks for sender, receiver, client IP
* Authentication support with file (LOGIN, PLAIN)
* Enforce encryption for authentication
* Forwards all mail to a smarthost (any SMTP server)
* Small codebase
* IPv6 support

View File

@@ -0,0 +1,11 @@
[Unit]
Description=Smtp relay Service
After=network.target
[Service]
ExecStart=/var/deploy/apps/smtprelay/smtprelay -config /var/deploy/apps/smtprelay/secrets/smtprelay.ini
Restart=always
User=root
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,27 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: adminer
labels:
app: adminer
spec:
selector:
matchLabels:
app: adminer
template:
metadata:
labels:
app: adminer
spec:
containers:
- name: adminer
image: docker.io/library/adminer:5.2.1
ports:
- containerPort: 8080
resources:
requests:
cpu: "0.1"
memory: 50Mi
limits:
cpu: "0.1"
memory: 100Mi

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: adminer-service
spec:
selector:
app: adminer
type: ClusterIP
ports:
- name: adminer
protocol: TCP
port: 80
targetPort: 8080

View File

@@ -0,0 +1,5 @@
```sh
kubectl apply -f admin-secret.yaml,db-secret.yaml
helm repo add gitea-charts https://dl.gitea.com/charts/
helm repo update
```

View File

@@ -0,0 +1,131 @@
replicaCount: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
image:
registry: docker.gitea.com
repository: gitea
tag: "1.21.11"
pullPolicy: IfNotPresent
rootless: true
ingress:
enabled: false
service:
http:
type: ClusterIP
targetPort: 3000
port: 3000
annotations: {}
gitea:
admin:
existingSecret: "gitea-admin-secret"
email: "vloldik@openvibes.ru"
passwordMode: initialOnlyRequireReset
config:
server:
ROOT_URL: "https://git.openvibes.ru/"
DOMAIN: "git.openvibes.ru"
SSH_DOMAIN: "git.openvibes.ru"
APP_NAME: "Openvibes Git"
service:
DISABLE_REGISTRATION: true
REQUIRE_SIGNIN_VIEW: false
repository:
ENABLE_PUSH_CREATE_USER: true
ENABLE_PUSH_CREATE_ORG: true
database:
DB_TYPE: postgres
HOST: "postgres-service-headless:5432"
NAME: "gitea"
USER: "gitea"
security:
INSTALL_LOCK: true
PASSWORD_COMPLEXITY: "medium"
MIN_PASSWORD_LENGTH: 8
log:
ROOT_PATH: /data/gitea/log
LEVEL: Info
mailer:
ENABLED: true
FORCE_TRUST_SERVER_CERT: true
FROM: gitea@mail.openvibes.ru
PROTOCOL: smtps
ENVELOPE_FROM: gitea@mail.openvibes.ru
additionalConfigFromEnvs:
- name: GITEA__DATABASE__PASSWD
valueFrom:
secretKeyRef:
name: "gitea-db-secret"
key: "db-password"
- name: GITEA__MAILER__SMTP_ADDR
valueFrom:
secretKeyRef:
name: "gitea-mailer-secret"
key: "smtp-server"
- name: GITEA__MAILER__SMTP_PORT
valueFrom:
secretKeyRef:
name: "gitea-mailer-secret"
key: "smtp-port"
- name: GITEA__MAILER__USER
valueFrom:
secretKeyRef:
name: "gitea-mailer-secret"
key: "smtp-login"
- name: GITEA__MAILER__PASSWD
valueFrom:
secretKeyRef:
name: "gitea-mailer-secret"
key: "smtp-password"
metrics:
enabled: true
serviceMonitor:
enabled: false
persistence:
enabled: true
storageClass: "local-path"
accessModes:
- ReadWriteOnce
size: 20Gi
deployment:
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 2
memory: 2Gi
postgresql:
enabled: false
postgresql-ha:
enabled: false
valkey:
enabled: true
valkey-cluster:
enabled: false
redis:
enabled: true
redis-cluster:
enabled: false

View File

@@ -0,0 +1,12 @@
kind: ConfigMap
apiVersion: v1
metadata:
name: planka-env
data:
BASE_URL: https://pm.openvibes.ru
TOKEN_EXPIRES_IN: "7"
DEFAULT_ADMIN_NAME: Vladislav
DEFAULT_ADMIN_USERNAME: vlad
DEFAULT_ADMIN_EMAIL: admin@openvibes.ru
SMTP_FROM: Planka Service <planka@mail.openvibes.ru>
SMTP_TLS_REJECT_UNAUTHORIZED: "false"

View File

@@ -0,0 +1,68 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: planka
labels:
app: planka
spec:
selector:
matchLabels:
app: planka
template:
metadata:
labels:
app: planka
spec:
containers:
- name: planka
image: ghcr.io/plankanban/planka:1.26.1
resources:
requests:
cpu: 50m
memory: 100Mi
limits:
cpu: 300m
memory: 500Mi
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: planka-secrets
key: database-url
- name: DEFAULT_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: planka-secrets
key: default-admin-password
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: planka-secrets
key: secret-key
envFrom:
- configMapRef:
name: planka-env
- secretRef:
name: planka-mail-secret
ports:
- containerPort: 1337
name: planka
volumeMounts:
- name: user-avatars
mountPath: /app/public/user-avatars
- name: background-images
mountPath: /app/public/project-background-images
- name: attachments
mountPath: /app/private/attachments
volumes:
- name: user-avatars
persistentVolumeClaim:
claimName: planka-user-avatars
- name: background-images
persistentVolumeClaim:
claimName: planka-background-images
- name: attachments
persistentVolumeClaim:
claimName: planka-attachments
restartPolicy: Always

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: planka-attachments
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: planka-background-images
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: planka-user-avatars
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: planka-service-headless
spec:
selector:
app: planka
type: ClusterIP
clusterIP: None
ports:
- name: http
protocol: TCP
port: 80
targetPort: 1337

View File

@@ -0,0 +1,40 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
labels:
app: postgres
spec:
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: docker.io/library/postgres:16-alpine
ports:
- containerPort: 5432
resources:
requests:
cpu: "0.1"
memory: 100Mi
limits:
cpu: "0.5"
memory: 1Gi
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secrets
key: admin-password
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 10Gi

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: postgres-service-headless
spec:
selector:
app: postgres
type: ClusterIP
clusterIP: None
ports:
- name: postgres-service
protocol: TCP
port: 5432
targetPort: 5432

View File

@@ -0,0 +1,10 @@
kind: ConfigMap
apiVersion: v1
metadata:
labels:
instance: vaultwarden
name: vaultwarden-env
data:
SIGNUPS_ALLOWED: "false"
DOMAIN: https://warden.openvibes.ru
ROCKET_ADDRESS: '::'

View File

@@ -0,0 +1,43 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: vaultwarden
labels:
app: vaultwarden
instance: vaultwarden
spec:
selector:
matchLabels:
app: vaultwarden
replicas: 1
template:
metadata:
labels:
app: vaultwarden
spec:
containers:
- name: vaultwarden
image: docker.io/vaultwarden/server:1.33.2-alpine
resources:
requests:
cpu: 300m
memory: 500Mi
limits:
cpu: "1"
memory: 1Gi
envFrom:
- configMapRef:
name: vaultwarden-env
- secretRef:
name: vaultwarden-secrets
ports:
- containerPort: 80
name: vaultwarden
volumeMounts:
- name: storage
mountPath: /data
volumes:
- name: storage
persistentVolumeClaim:
claimName: vaultwarden-pvc
restartPolicy: Always

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
instance: vaultwarden
name: vaultwarden-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 10Gi

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: vaultwarden-service-headless
labels:
instance: vaultwarden
spec:
selector:
app: vaultwarden
type: ClusterIP
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80

View File

@@ -0,0 +1 @@
## Сертификат, описание issuer для letsencrypt скрыты.

View File

@@ -0,0 +1,28 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dbadmin-ingress
annotations:
spec.ingressClassName: traefik
cert-manager.io/cluster-issuer: letsencrypt-openvibes-issuer
traefik.ingress.kubernetes.io/router.middlewares: openvibes-redirect-https@kubernetescrd
traefik.ingress.kubernetes.io/router.tls.options: openvibes-user-validate-tls@kubernetescrd
spec:
ingressClassName: traefik
rules:
- host: dbadmin.openvibes.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: adminer-service
port:
number: 80
tls:
- secretName: dbadmin-tls
hosts:
- dbadmin.openvibes.ru

View File

@@ -0,0 +1,27 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: git-ingress
annotations:
spec.ingressClassName: traefik
cert-manager.io/cluster-issuer: letsencrypt-openvibes-issuer
traefik.ingress.kubernetes.io/router.middlewares: openvibes-redirect-https@kubernetescrd
spec:
ingressClassName: traefik
rules:
- host: git.openvibes.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gitea-http
port:
number: 3000
tls:
- secretName: git-tls
hosts:
- git.openvibes.ru

View File

@@ -0,0 +1,27 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pm-ingress
annotations:
spec.ingressClassName: traefik
cert-manager.io/cluster-issuer: letsencrypt-openvibes-issuer
traefik.ingress.kubernetes.io/router.middlewares: openvibes-redirect-https@kubernetescrd
spec:
ingressClassName: traefik
rules:
- host: pm.openvibes.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: planka-service-headless
port:
number: 80
tls:
- secretName: pm-tls
hosts:
- pm.openvibes.ru

View File

@@ -0,0 +1,27 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: warden-ingress
annotations:
spec.ingressClassName: traefik
cert-manager.io/cluster-issuer: letsencrypt-openvibes-issuer
traefik.ingress.kubernetes.io/router.middlewares: openvibes-redirect-https@kubernetescrd
spec:
ingressClassName: traefik
rules:
- host: warden.openvibes.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: vaultwarden-service-headless
port:
number: 80
tls:
- secretName: warden-tls
hosts:
- warden.openvibes.ru

6
secrets/Readme.md Normal file
View File

@@ -0,0 +1,6 @@
# Для создания самоподписанного сертификата пользователя
1. `openssl genrsa -out myuser.key 2048`
2. `openssl req -new -key myuser.key -out myuser.csr`
3. `openssl x509 -req -in myuser.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out myuser.crt -days 365 -sha256`
4. `openssl pkcs12 -export -out myuser.pfx -inkey myuser.key -in myuser.crt`