Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,19 @@ SWAGGER_ADDRESS_PORT=

# Server
SITE_ADDR=0.0.0.0:3000
# Comma-separated reverse proxy IPs/CIDRs. Use "none" when directly exposed.
TRUSTED_PROXIES=127.0.0.1,::1

# Logging
LOG_LEVEL=INFO
LOG_PATH=

# Cache
CACHE_TYPE=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_USERNAME=
REDIS_PASSWORD=
REDIS_DB=0
REDIS_KEY_PREFIX=hnu-forum:
REDIS_POOL_SIZE=20
70 changes: 70 additions & 0 deletions .github/workflows/build-production-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

name: Build Production Image

on:
workflow_dispatch:
push:
branches:
- main

permissions:
contents: read
packages: write

concurrency:
group: production-image
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 90

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: true
pull: true
tags: |
ghcr.io/irofahaxikk/hnu-forum:production
ghcr.io/irofahaxikk/hnu-forum:sha-${{ github.sha }}
labels: |
org.opencontainers.image.source=https://github.com/IroFahaxikk/hnu-forum
org.opencontainers.image.revision=${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
GOPROXY=https://proxy.golang.org,direct
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ dist/
.husky/

# Environment variables
.env
.env
/deploy/production/.env

AGENT.md
3 changes: 3 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ func runApp() {
}

func newApplication(serverConf *conf.Server, server *gin.Engine, manager *cron.ScheduledTaskManager) *pacman.Application {
if err := server.SetTrustedProxies(serverConf.HTTP.TrustedProxies); err != nil {
panic(err)
}
manager.Run()
return pacman.NewApp(
pacman.WithName(Name),
Expand Down
13 changes: 10 additions & 3 deletions cmd/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion configs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,25 @@
server:
http:
addr: 0.0.0.0:80
# Trust only the reverse proxy that directly connects to Answer.
trusted_proxies:
- 127.0.0.1
- ::1
data:
database:
driver: "sqlite3"
connection: "/data/sqlite3/answer.db"
cache:
type: "redis"
file_path: "/data/cache/cache.db"
redis:
host: "127.0.0.1"
port: 6379
username: ""
password: ""
db: 0
key_prefix: "hnu-forum:"
pool_size: 20
i18n:
bundle_dir: "/data/i18n"
swaggerui:
Expand All @@ -41,4 +54,3 @@ ui:
api_url: '/'
base_url: ''
api_base_url: ''

13 changes: 13 additions & 0 deletions deploy/production/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
DOMAIN=dongpolakeside.com
HNU_DATA_ROOT=/srv/hnu-forum
ANSWER_IMAGE=ghcr.io/irofahaxikk/hnu-forum
IMAGE_TAG=production

GOPROXY=https://proxy.golang.org,direct

MYSQL_DATABASE=answer
MYSQL_USER=answer
MYSQL_PASSWORD=replace_with_generated_secret
MYSQL_ROOT_PASSWORD=replace_with_generated_secret

REDIS_PASSWORD=replace_with_generated_secret
120 changes: 120 additions & 0 deletions deploy/production/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

name: hnu-forum

x-logging: &default-logging
driver: json-file
options:
max-size: "10m"
max-file: "3"

services:
mysql:
image: mysql:8.4
restart: unless-stopped
environment:
TZ: Asia/Hong_Kong
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?MYSQL_ROOT_PASSWORD is required}
MYSQL_DATABASE: ${MYSQL_DATABASE:-answer}
MYSQL_USER: ${MYSQL_USER:-answer}
MYSQL_PASSWORD: ${MYSQL_PASSWORD:?MYSQL_PASSWORD is required}
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --default-time-zone=+08:00
- --innodb-buffer-pool-size=384M
- --max-connections=100
volumes:
- ${HNU_DATA_ROOT:-/srv/hnu-forum}/mysql:/var/lib/mysql
healthcheck:
test:
- CMD-SHELL
- mysqladmin ping -h 127.0.0.1 -uroot -p"$${MYSQL_ROOT_PASSWORD}" --silent
interval: 10s
timeout: 5s
retries: 20
networks:
- backend
mem_limit: 768m
logging: *default-logging

redis:
image: redis:7.4-alpine
restart: unless-stopped
environment:
TZ: Asia/Hong_Kong
REDIS_PASSWORD: ${REDIS_PASSWORD:?REDIS_PASSWORD is required}
command:
- sh
- -c
- exec redis-server --appendonly yes --requirepass "$$REDIS_PASSWORD" --maxmemory 128mb --maxmemory-policy allkeys-lru
volumes:
- ${HNU_DATA_ROOT:-/srv/hnu-forum}/redis:/data
healthcheck:
test:
- CMD-SHELL
- redis-cli -a "$${REDIS_PASSWORD}" ping | grep -q PONG
interval: 10s
timeout: 5s
retries: 20
networks:
- backend
mem_limit: 256m
logging: *default-logging

answer:
image: ${ANSWER_IMAGE:-ghcr.io/irofahaxikk/hnu-forum}:${IMAGE_TAG:-production}
pull_policy: always
restart: unless-stopped
environment:
TZ: Asia/Hong_Kong
SITE_ADDR: 0.0.0.0:80
CACHE_TYPE: redis
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:?REDIS_PASSWORD is required}
REDIS_DB: 0
REDIS_KEY_PREFIX: "hnu-forum:"
REDIS_POOL_SIZE: 10
TRUSTED_PROXIES: 172.16.0.0/12
SWAGGER_HOST: ${DOMAIN:-dongpolakeside.com}
SWAGGER_ADDRESS_PORT: ":443"
ports:
- 127.0.0.1:9080:80
volumes:
- ${HNU_DATA_ROOT:-/srv/hnu-forum}/answer:/data
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test:
- CMD-SHELL
- curl -fsS http://127.0.0.1/ >/dev/null || exit 1
interval: 15s
timeout: 5s
retries: 20
networks:
- backend
mem_limit: 1g
logging: *default-logging

networks:
backend:
driver: bridge
Loading