feat: add gitea to the docker stack
This commit is contained in:
parent
fdf2db9e4e
commit
378585875c
12 changed files with 334 additions and 103 deletions
|
@ -26,8 +26,7 @@ type DockerNetworkConfig struct {
|
||||||
Driver string `json:"driver"`
|
Driver string `json:"driver"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DockerSharedVolumeConfig contains configuration
|
// DockerSharedVolumeConfig contains configuration for creating the shared volume.
|
||||||
// for creating the shared volume.
|
|
||||||
type DockerSharedVolumeConfig struct {
|
type DockerSharedVolumeConfig struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
@ -35,6 +34,7 @@ type DockerSharedVolumeConfig struct {
|
||||||
// Services contains a list of services and their configuration.
|
// Services contains a list of services and their configuration.
|
||||||
type ServicesConfig struct {
|
type ServicesConfig struct {
|
||||||
Traefik TraefikConfig `json:"traefik"`
|
Traefik TraefikConfig `json:"traefik"`
|
||||||
|
Gitea GiteaConfig `json:"gitea"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraefikConfig contains configuration for the Traefik container.
|
// TraefikConfig contains configuration for the Traefik container.
|
||||||
|
@ -48,8 +48,27 @@ type TraefikConfig struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig creates a new Config value from a given
|
// GiteaConfig contains configuration for the Gitea container.
|
||||||
// JSON file.
|
type GiteaConfig struct {
|
||||||
|
AppName string `json:"appName"`
|
||||||
|
BaseUri string `json:"baseUri"`
|
||||||
|
ContainerIp string `json:"containerIp"`
|
||||||
|
DataDirectory string `json:"dataDirectory"`
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
GroupId int
|
||||||
|
HttpPort int `json:"httpPort"`
|
||||||
|
InternalToken string `json:"internalToken"`
|
||||||
|
LogLevel string `json:"logLevel"`
|
||||||
|
RootUrl string `json:"rootUrl"`
|
||||||
|
RunMode string `json:"runMode"`
|
||||||
|
SecretKey string `json:"secretKey"`
|
||||||
|
SshDomain string `json:"sshDomain"`
|
||||||
|
SshPort int `json:"sshPort"`
|
||||||
|
UserId int
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConfig creates a new Config value from a given JSON file.
|
||||||
func NewConfig(file string) (Config, error) {
|
func NewConfig(file string) (Config, error) {
|
||||||
var c Config
|
var c Config
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -31,11 +31,29 @@ func TestValidConfig(t *testing.T) {
|
||||||
Traefik: TraefikConfig{
|
Traefik: TraefikConfig{
|
||||||
CheckNewVersion: true,
|
CheckNewVersion: true,
|
||||||
ContainerIp: "172.17.1.2",
|
ContainerIp: "172.17.1.2",
|
||||||
Domain: "forge.localhost",
|
Domain: "forge.test.local",
|
||||||
LogLevel: "info",
|
LogLevel: "info",
|
||||||
SendAnonymousUsage: false,
|
SendAnonymousUsage: false,
|
||||||
Version: "v2.4.9",
|
Version: "v2.4.9",
|
||||||
},
|
},
|
||||||
|
Gitea: GiteaConfig{
|
||||||
|
AppName: "A git hosting platform",
|
||||||
|
BaseUri: "git",
|
||||||
|
ContainerIp: "172.17.1.3",
|
||||||
|
DataDirectory: "/helix/data/gitea",
|
||||||
|
Domain: "forge.test.local",
|
||||||
|
GroupId: 0,
|
||||||
|
HttpPort: 3000,
|
||||||
|
InternalToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE2MjY0ODQxNjV9.Lp2v7vluALZtAng1jte5-SvF69iAUoh9pFBxf-IJ1a0",
|
||||||
|
LogLevel: "info",
|
||||||
|
RootUrl: "https://forge.test.local/git",
|
||||||
|
RunMode: "test",
|
||||||
|
SecretKey: "gBFbTiV4GTwzonAyyHNKghc9lmWvaTmFqZs5u0h14Qgx5yp1OKlrZKgw1e5LfCiE",
|
||||||
|
SshDomain: "forge.test.local",
|
||||||
|
SshPort: 2222,
|
||||||
|
UserId: 0,
|
||||||
|
Version: "1.14.4",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
22
internal/config/testdata/config-valid.json
vendored
22
internal/config/testdata/config-valid.json
vendored
|
@ -13,11 +13,27 @@
|
||||||
"services": {
|
"services": {
|
||||||
"traefik": {
|
"traefik": {
|
||||||
"checkNewVersion": true,
|
"checkNewVersion": true,
|
||||||
"sendAnonymousUsage": false,
|
|
||||||
"version": "v2.4.9",
|
|
||||||
"containerIp": "172.17.1.2",
|
"containerIp": "172.17.1.2",
|
||||||
|
"domain": "forge.test.local",
|
||||||
"logLevel": "info",
|
"logLevel": "info",
|
||||||
"domain": "forge.localhost"
|
"sendAnonymousUsage": false,
|
||||||
|
"version": "v2.4.9"
|
||||||
|
},
|
||||||
|
"gitea": {
|
||||||
|
"appName": "A git hosting platform",
|
||||||
|
"baseUri": "git",
|
||||||
|
"containerIp": "172.17.1.3",
|
||||||
|
"dataDirectory": "/helix/data/gitea",
|
||||||
|
"domain": "forge.test.local",
|
||||||
|
"httpPort": 3000,
|
||||||
|
"internalToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE2MjY0ODQxNjV9.Lp2v7vluALZtAng1jte5-SvF69iAUoh9pFBxf-IJ1a0",
|
||||||
|
"logLevel": "info",
|
||||||
|
"rootUrl": "https://forge.test.local/git",
|
||||||
|
"runMode": "test",
|
||||||
|
"secretKey": "gBFbTiV4GTwzonAyyHNKghc9lmWvaTmFqZs5u0h14Qgx5yp1OKlrZKgw1e5LfCiE",
|
||||||
|
"sshDomain": "forge.test.local",
|
||||||
|
"sshPort": 2222,
|
||||||
|
"version": "1.14.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ type DockerVolume struct {
|
||||||
MountPath pulumi.StringInput
|
MountPath pulumi.StringInput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateContainer creates and runs a new container.
|
||||||
func CreateContainer(ctx *pulumi.Context, c DockerContainerInput) error {
|
func CreateContainer(ctx *pulumi.Context, c DockerContainerInput) error {
|
||||||
// all containers will mount the host's timezone and localtime files
|
// all containers will mount the host's timezone and localtime files
|
||||||
// to ensure the correct time is synced.
|
// to ensure the correct time is synced.
|
||||||
|
|
|
@ -2,7 +2,7 @@ package stacks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
_ "embed"
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -23,17 +23,8 @@ type DockerStack struct {
|
||||||
Stack auto.Stack
|
Stack auto.Stack
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed templates/traefik/Dockerfile.tmpl
|
//go:embed templates/*
|
||||||
var templateTraefikDockerfile string
|
var templates embed.FS
|
||||||
|
|
||||||
//go:embed templates/traefik/traefik.yaml.tmpl
|
|
||||||
var templateTraefikStaticConfig string
|
|
||||||
|
|
||||||
//go:embed templates/traefik/dynamic_dashboard.yaml.tmpl
|
|
||||||
var templateTraefikDynamicDashboardConfig string
|
|
||||||
|
|
||||||
//go:embed templates/traefik/entrypoint.sh.tmpl
|
|
||||||
var templateTraefikEntrypoint string
|
|
||||||
|
|
||||||
// newContainerStack creates the ContainerStack value.
|
// newContainerStack creates the ContainerStack value.
|
||||||
func newDockerStack(ctx context.Context, project, stack string, c config.Config) (*DockerStack, error) {
|
func newDockerStack(ctx context.Context, project, stack string, c config.Config) (*DockerStack, error) {
|
||||||
|
@ -52,7 +43,7 @@ func newDockerStack(ctx context.Context, project, stack string, c config.Config)
|
||||||
return &d, nil
|
return &d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preview the proposed changes to the container stack.
|
// Preview the proposed changes to the docker stack.
|
||||||
func (c *DockerStack) Preview(ctx context.Context) error {
|
func (c *DockerStack) Preview(ctx context.Context) error {
|
||||||
streamer := optpreview.ProgressStreams(os.Stdout)
|
streamer := optpreview.ProgressStreams(os.Stdout)
|
||||||
_, err := c.Stack.Preview(ctx, streamer)
|
_, err := c.Stack.Preview(ctx, streamer)
|
||||||
|
@ -62,7 +53,7 @@ func (c *DockerStack) Preview(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the container stack.
|
// Update the docker stack.
|
||||||
func (c *DockerStack) Update(ctx context.Context) error {
|
func (c *DockerStack) Update(ctx context.Context) error {
|
||||||
streamer := optup.ProgressStreams(os.Stdout)
|
streamer := optup.ProgressStreams(os.Stdout)
|
||||||
_, err := c.Stack.Up(ctx, streamer)
|
_, err := c.Stack.Up(ctx, streamer)
|
||||||
|
@ -72,7 +63,7 @@ func (c *DockerStack) Update(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the container stack.
|
// Destroy the docker stack.
|
||||||
func (c *DockerStack) Destroy(ctx context.Context) error {
|
func (c *DockerStack) Destroy(ctx context.Context) error {
|
||||||
streamer := optdestroy.ProgressStreams(os.Stdout)
|
streamer := optdestroy.ProgressStreams(os.Stdout)
|
||||||
_, err := c.Stack.Destroy(ctx, streamer)
|
_, err := c.Stack.Destroy(ctx, streamer)
|
||||||
|
@ -82,11 +73,16 @@ func (c *DockerStack) Destroy(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// deployDockerStack returns a Pulumi run function
|
// deployDockerStack returns a Pulumi run function that is used to deploy the docker stack.
|
||||||
// that is used to deploy the docker stack.
|
|
||||||
func deployDockerStack(project string, dockerConfig config.DockerConfig, services config.ServicesConfig) pulumi.RunFunc {
|
func deployDockerStack(project string, dockerConfig config.DockerConfig, services config.ServicesConfig) pulumi.RunFunc {
|
||||||
groupID := 2239
|
sharedVolumeMountPath := "/helix/shared"
|
||||||
services.Traefik.GroupId = groupID
|
|
||||||
|
groupId := 2239
|
||||||
|
|
||||||
|
services.Traefik.GroupId = groupId
|
||||||
|
|
||||||
|
services.Gitea.GroupId = groupId
|
||||||
|
services.Gitea.UserId = 2000
|
||||||
|
|
||||||
return func(ctx *pulumi.Context) error {
|
return func(ctx *pulumi.Context) error {
|
||||||
// TODO: Create the provider when we start playing with remote hosts
|
// TODO: Create the provider when we start playing with remote hosts
|
||||||
|
@ -114,43 +110,27 @@ func deployDockerStack(project string, dockerConfig config.DockerConfig, service
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
base_cache, err := os.UserCacheDir()
|
baseCache, err := os.UserCacheDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get the base cache directory...\n%w", err)
|
return fmt.Errorf("unable to get the base cache directory...\n%w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the Traefik service
|
projectCacheRoot := filepath.Join(baseCache, "helix", project)
|
||||||
traefikContextDir := filepath.Join(base_cache, "helix", project, "traefik")
|
|
||||||
|
|
||||||
if err := os.MkdirAll(traefikContextDir, 0700); err != nil {
|
// Traefik service.
|
||||||
return fmt.Errorf("unable to make the cache directory for traefik...\n%w", err)
|
if err = renderTemplates(services.Traefik, "traefik", projectCacheRoot); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := generateFile(services.Traefik, templateTraefikDockerfile, "traefikDocker", filepath.Join(traefikContextDir, "Dockerfile")); err != nil {
|
traefikImageInput := docker.DockerImageInput{
|
||||||
return fmt.Errorf("unable to generate the Traefik Dockerfile from template...\n%w", err)
|
BuildContext: pulumi.String(filepath.Join(projectCacheRoot, "traefik")),
|
||||||
}
|
Dockerfile: pulumi.String(filepath.Join(projectCacheRoot, "traefik", "Dockerfile")),
|
||||||
|
|
||||||
if err := generateFile(services.Traefik, templateTraefikStaticConfig, "traefikStaticConf", filepath.Join(traefikContextDir, "traefik.yml")); err != nil {
|
|
||||||
return fmt.Errorf("unable to generate the Traefik static configuration from template...\n%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := generateFile(services.Traefik, templateTraefikDynamicDashboardConfig, "traefikDashboardConf", filepath.Join(traefikContextDir, "dynamic_dashboard.yaml")); err != nil {
|
|
||||||
return fmt.Errorf("unable to generate the Traefik dashboard configuration from template...\n%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := generateFile(services.Traefik, templateTraefikEntrypoint, "traefikEntrypoint", filepath.Join(traefikContextDir, "entrypoint.sh")); err != nil {
|
|
||||||
return fmt.Errorf("unable to generate the Traefik entrypoint script from template...\n%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := docker.DockerImageInput{
|
|
||||||
BuildContext: pulumi.String(traefikContextDir),
|
|
||||||
Dockerfile: pulumi.String(filepath.Join(traefikContextDir, "Dockerfile")),
|
|
||||||
ImageName: pulumi.String("helix-traefik"),
|
ImageName: pulumi.String("helix-traefik"),
|
||||||
ImageTag: pulumi.String(services.Traefik.Version),
|
ImageTag: pulumi.String(services.Traefik.Version),
|
||||||
UniqueLabel: "traefik-image",
|
UniqueLabel: "traefik-image",
|
||||||
}
|
}
|
||||||
|
|
||||||
traefikImage, err := docker.CreateImage(ctx, c)
|
traefikImage, err := docker.CreateImage(ctx, traefikImageInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -164,7 +144,7 @@ func deployDockerStack(project string, dockerConfig config.DockerConfig, service
|
||||||
DockerVolumes: []docker.DockerVolume{
|
DockerVolumes: []docker.DockerVolume{
|
||||||
{
|
{
|
||||||
Name: sharedVolume.Name,
|
Name: sharedVolume.Name,
|
||||||
MountPath: pulumi.String("/helix/shared"),
|
MountPath: pulumi.String(sharedVolumeMountPath),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -173,6 +153,48 @@ func deployDockerStack(project string, dockerConfig config.DockerConfig, service
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gitea service
|
||||||
|
if err = renderTemplates(services.Gitea, "gitea", projectCacheRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
giteaImageInput := docker.DockerImageInput{
|
||||||
|
BuildContext: pulumi.String(filepath.Join(projectCacheRoot, "gitea")),
|
||||||
|
Dockerfile: pulumi.String(filepath.Join(projectCacheRoot, "gitea", "Dockerfile")),
|
||||||
|
ImageName: pulumi.String("helix-gitea"),
|
||||||
|
ImageTag: pulumi.String(services.Gitea.Version),
|
||||||
|
UniqueLabel: "gitea-image",
|
||||||
|
}
|
||||||
|
|
||||||
|
giteaImage, err := docker.CreateImage(ctx, giteaImageInput)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
giteaContainerInput := docker.DockerContainerInput{
|
||||||
|
Image: giteaImage.ImageName,
|
||||||
|
Ipv4Address: pulumi.String(services.Gitea.ContainerIp),
|
||||||
|
Name: pulumi.String("helix-gitea"),
|
||||||
|
Network: network.Name,
|
||||||
|
DockerVolumes: []docker.DockerVolume{
|
||||||
|
{
|
||||||
|
Name: sharedVolume.Name,
|
||||||
|
MountPath: pulumi.String(sharedVolumeMountPath),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HostPathVolumes: []docker.HostPathVolume{
|
||||||
|
{
|
||||||
|
HostPath: pulumi.String(services.Gitea.DataDirectory),
|
||||||
|
MountPath: pulumi.String("/helix/gitea/data"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
UniqueLabel: "gitea-container",
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = docker.CreateContainer(ctx, giteaContainerInput); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,57 @@ package stacks
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
// generateFile renders a given template to a given filepath.
|
// renderTemplates renders all template files (.tmpl) within a given directory in the
|
||||||
func generateFile(data interface{}, templateString, templateName, path string) error {
|
// embedded 'templates' filesystem.
|
||||||
file, err := os.Create(path)
|
func renderTemplates(data interface{}, service, projectCacheRoot string) error {
|
||||||
|
// create the context directory
|
||||||
|
contextDir := filepath.Join(projectCacheRoot, service)
|
||||||
|
|
||||||
|
if err := os.MkdirAll(contextDir, 0700); err != nil {
|
||||||
|
return fmt.Errorf("unable to make the cache directory for %s...\n%w", service, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the service's template directory to get the list of the template files.
|
||||||
|
templateDir := "templates/" + service
|
||||||
|
|
||||||
|
fsDir, err := templates.ReadDir(templateDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create the file '%s'...\n%v", path, err)
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// render each template file (.tmpl) to the context directory.
|
||||||
|
for _, f := range fsDir {
|
||||||
|
filename := f.Name()
|
||||||
|
|
||||||
|
content, err := templates.ReadFile(fmt.Sprintf("%s/%s", templateDir, filename))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFilename := strings.TrimSuffix(filename, ".tmpl")
|
||||||
|
outputPath := filepath.Join(contextDir, outputFilename)
|
||||||
|
|
||||||
|
file, err := os.Create(outputPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to create the file '%s'...\n%v", outputPath, err)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
tmpl := template.Must(template.New(templateName).Parse(templateString))
|
if !strings.HasSuffix(filename, ".tmpl") {
|
||||||
|
fmt.Fprint(file, string(content))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl := template.Must(template.New(filename).Parse(string(content)))
|
||||||
|
|
||||||
if err = tmpl.Execute(file, data); err != nil {
|
if err = tmpl.Execute(file, data); err != nil {
|
||||||
return fmt.Errorf("unable to execute the template at '%s'...\n%v", path, err)
|
return fmt.Errorf("unable to execute the template at '%s'...\n%v", outputFilename, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,15 +1,55 @@
|
||||||
{{/* vim: set ft=dockerfile : */}}
|
# This is a helix flavoured Dockerfile for Gitea which is inspired from
|
||||||
|
# the official Dockerfile.rootless from https://github.com/go-gitea/gitea/
|
||||||
|
|
||||||
ARG GITEA_VERSION={{ .Version }}
|
FROM alpine:3.14.0 AS verifier
|
||||||
|
|
||||||
FROM gitea/gitea:${GITEA_VERSION}
|
RUN apk --no-cache add gnupg curl && \
|
||||||
|
curl -L https://dl.gitea.io/gitea/{{ .Version }}/gitea-{{ .Version }}-linux-amd64 -o /gitea && \
|
||||||
|
curl -L https://dl.gitea.io/gitea/{{ .Version }}/gitea-{{ .Version }}-linux-amd64.asc -o /gitea.asc && \
|
||||||
|
gpg --keyserver keys.openpgp.org --recv 7C9E68152594688862D62AF62D9AE806EC1592E2 && \
|
||||||
|
gpg --verify /gitea.asc /gitea
|
||||||
|
|
||||||
ENV USER_UID=1000 \
|
|
||||||
USER_GID=1000 \
|
|
||||||
GITEA_CUSTOM=/helix/gitea/custom
|
|
||||||
|
|
||||||
ADD files app.ini /helix/gitea/custom/app.ini
|
FROM alpine:3.14.0
|
||||||
|
|
||||||
RUN chown -R ${USER_ID}:${USER_GID} /helix
|
RUN apk --no-cache add \
|
||||||
|
bash \
|
||||||
|
ca-certificates \
|
||||||
|
gettext \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
gnupg
|
||||||
|
|
||||||
EXPOSE {{ .App.HttpPort }} {{ .App.SshPort }}
|
RUN addgroup -S -g {{ .GroupId }} git && \
|
||||||
|
adduser -S -H -D -h /helix/gitea/data/home -s /bin/bash -u {{ .UserId }} -G git git && \
|
||||||
|
mkdir -p /helix/gitea/data /helix/gitea/tmp && \
|
||||||
|
chown git:git /helix/gitea/data && chmod 0700 /helix/gitea/data && \
|
||||||
|
chown git:git /helix/gitea/tmp && chmod 0700 /helix/gitea/tmp
|
||||||
|
|
||||||
|
COPY --from=verifier --chown=root:root /gitea /usr/local/bin/gitea
|
||||||
|
ADD app.ini /helix/gitea/config/
|
||||||
|
ADD entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
|
ADD --chown={{ .UserId }}:{{ .GroupId }} dynamic_git.yaml /helix/gitea/tmp/
|
||||||
|
|
||||||
|
RUN chown -R git:git /helix/gitea/config/app.ini && \
|
||||||
|
chmod 0400 /helix/gitea/config/app.ini && \
|
||||||
|
chmod a+x /usr/local/bin/gitea && \
|
||||||
|
chmod a+x /usr/local/bin/entrypoint.sh
|
||||||
|
|
||||||
|
ENV GITEA_WORK_DIR=/helix/gitea/data \
|
||||||
|
GITEA_CUSTOM=/helix/gitea/data/custom \
|
||||||
|
GITEA_APP_INI=/helix/gitea/config/app.ini \
|
||||||
|
GITEA_BIN=/usr/local/bin/gitea \
|
||||||
|
HOME=/helix/gitea/data/home
|
||||||
|
|
||||||
|
USER {{ .UserId }}:{{ .GroupId }}
|
||||||
|
|
||||||
|
WORKDIR /helix/gitea/data
|
||||||
|
|
||||||
|
VOLUME ["/helix/gitea/data"]
|
||||||
|
|
||||||
|
EXPOSE {{ .HttpPort }} {{ .SshPort }}
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
|
|
||||||
|
CMD []
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
{{/* vim: set ft=dosini : */}}
|
APP_NAME = {{ .AppName }}
|
||||||
APP_NAME = {{ .App.Name }}
|
RUN_USER = git
|
||||||
RUN_MODE = {{ .App.RunMode }}
|
RUN_MODE = {{ .RunMode }}
|
||||||
|
|
||||||
[repository]
|
[repository]
|
||||||
ROOT = /data/gitea/repositories
|
ROOT = /helix/gitea/data/git/repositories
|
||||||
DEFAULT_BRANCH = main
|
DEFAULT_BRANCH = main
|
||||||
|
|
||||||
[repository.local]
|
[repository.local]
|
||||||
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
|
LOCAL_COPY_PATH = /helix/gitea/tmp/local-repo
|
||||||
|
|
||||||
[repository.upload]
|
[repository.upload]
|
||||||
TEMP_PATH = /data/gitea/uploads
|
TEMP_PATH = /helix/gitea/tmp/uploads
|
||||||
|
|
||||||
[repository.signing]
|
[repository.signing]
|
||||||
; Gitea will sign initial commits only if the user has a public key.
|
; Gitea will sign initial commits only if the user has a public key.
|
||||||
|
@ -20,17 +20,18 @@ INITIAL_COMMIT = pubkey
|
||||||
DEFAULT_THEME = arc-green
|
DEFAULT_THEME = arc-green
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
APP_DATA_PATH = /data/gitea
|
APP_DATA_PATH = /helix/gitea/data/git
|
||||||
DOMAIN = {{ .App.Domain }}
|
DOMAIN = {{ .Domain }}
|
||||||
HTTP_ADDR = {{ .Container.Ip }}
|
HTTP_ADDR = {{ .ContainerIp }}
|
||||||
HTTP_PORT = {{ .App.HttpPort }}
|
HTTP_PORT = {{ .HttpPort }}
|
||||||
ROOT_URL = {{ .App.RootUrl }}
|
ROOT_URL = {{ .RootUrl }}
|
||||||
DISABLE_SSH = false
|
DISABLE_SSH = false
|
||||||
SSH_DOMAIN = {{ .App.SshDomain }}
|
SSH_DOMAIN = {{ .SshDomain }}
|
||||||
SSH_PORT = {{ .App.SshPort }}
|
SSH_PORT = {{ .SshPort }}
|
||||||
SSH_LISTEN_PORT = {{ .App.SshPort }}
|
SSH_LISTEN_PORT = {{ .SshPort }}
|
||||||
|
BUILTIN_SSH_SERVER_USER = git
|
||||||
LFS_START_SERVER = false
|
LFS_START_SERVER = false
|
||||||
LFS_CONTENT_PATH = /data/gitea/lfs
|
LFS_CONTENT_PATH = /helix/gitea/data/git/lfs
|
||||||
|
|
||||||
[ssh.minimum_key_sizes]
|
[ssh.minimum_key_sizes]
|
||||||
ED25519 = 256
|
ED25519 = 256
|
||||||
|
@ -40,16 +41,20 @@ DSA = -1
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
DB_TYPE = sqlite3
|
DB_TYPE = sqlite3
|
||||||
PATH = /data/gitea/database/gitea.db
|
PATH = /helix/gitea/data/database/gitea.db
|
||||||
|
HOST = localhost:3306
|
||||||
|
NAME = gitea
|
||||||
|
USER = gitea
|
||||||
|
PASSWD =
|
||||||
|
|
||||||
[indexer]
|
[indexer]
|
||||||
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
|
ISSUE_INDEXER_PATH = /helix/gitea/data/indexers/issues.bleve
|
||||||
|
|
||||||
[session]
|
[session]
|
||||||
PROVIDER_CONFIG = /data/gitea/sessions
|
PROVIDER_CONFIG = /helix/gitea/data/sessions
|
||||||
|
|
||||||
[queue]
|
[queue]
|
||||||
DATADIR = /data/gitea/queues
|
DATADIR = /helix/gitea/data/queues
|
||||||
|
|
||||||
[admin]
|
[admin]
|
||||||
DISABLE_REGULAR_ORG_CREATION = true
|
DISABLE_REGULAR_ORG_CREATION = true
|
||||||
|
@ -57,27 +62,30 @@ DEFAULT_EMAIL_NOTIFICATION = disabled
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
INSTALL_LOCK = true
|
INSTALL_LOCK = true
|
||||||
SECRET_KEY = {{ .App.SecretKey }}
|
SECRET_KEY = {{ .SecretKey }}
|
||||||
|
INTERNAL_TOKEN = {{ .InternalToken }}
|
||||||
LOGIN_REMEMBER_DAYS = 1
|
LOGIN_REMEMBER_DAYS = 1
|
||||||
MIN_PASSWORD_LENGTH = 12
|
MIN_PASSWORD_LENGTH = 12
|
||||||
PASSWORD_COMPLEXITY = lower,upper,digit
|
PASSWORD_COMPLEXITY = lower,upper,digit
|
||||||
|
|
||||||
[service]
|
[service]
|
||||||
DISABLED_REGISTRATION = true
|
DISABLE_REGISTRATION = true
|
||||||
|
|
||||||
|
[service.explore]
|
||||||
REQUIRE_SIGNIN_VIEW = false
|
REQUIRE_SIGNIN_VIEW = false
|
||||||
|
|
||||||
[picture]
|
[picture]
|
||||||
AVATAR_UPLOAD_PATH = /data/gitea/avatars
|
AVATAR_UPLOAD_PATH = /helix/gitea/data/avatars
|
||||||
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars
|
REPOSITORY_AVATAR_UPLOAD_PATH = /helix/gitea/data/repo-avatars
|
||||||
|
|
||||||
[attachment]
|
[attachment]
|
||||||
ENABLED = true
|
ENABLED = true
|
||||||
PATH = /data/gitea/attachments
|
PATH = /helix/gitea/data/attachments
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
ROOT_PATH = /data/gitea/log
|
ROOT_PATH = /helix/gitea/data/log
|
||||||
MODE = console
|
MODE = console
|
||||||
LEVEL = {{ .App.LogLevel }}
|
LEVEL = {{ .LogLevel }}
|
||||||
|
|
||||||
[log.console]
|
[log.console]
|
||||||
STDERR = false
|
STDERR = false
|
||||||
|
@ -90,3 +98,6 @@ NAMES = English
|
||||||
SHOW_FOOTER_BRANDING = true
|
SHOW_FOOTER_BRANDING = true
|
||||||
SHOW_FOOTER_VERSION = false
|
SHOW_FOOTER_VERSION = false
|
||||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
|
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
|
||||||
|
|
||||||
|
[oauth2]
|
||||||
|
ENABLE = false
|
||||||
|
|
34
internal/stacks/templates/gitea/dynamic_git.yaml.tmpl
Normal file
34
internal/stacks/templates/gitea/dynamic_git.yaml.tmpl
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
gitea:
|
||||||
|
entryPoints:
|
||||||
|
- "https"
|
||||||
|
rule: "Host(`{{ .Domain }}`) && PathPrefix(`/{{ .BaseUri }}`)"
|
||||||
|
service: "git"
|
||||||
|
middlewares:
|
||||||
|
- "git-strip-prefix"
|
||||||
|
tls: {}
|
||||||
|
middlewares:
|
||||||
|
git-strip-prefix:
|
||||||
|
stripPrefix:
|
||||||
|
prefixes:
|
||||||
|
- "/{{ .BaseUri }}"
|
||||||
|
services:
|
||||||
|
git:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- url: "http://{{ .ContainerIp }}:{{ .HttpPort }}/"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
gitSSH:
|
||||||
|
entryPoints:
|
||||||
|
- "ssh"
|
||||||
|
rule: "HostSNI(`*`)"
|
||||||
|
service: "gitSSH"
|
||||||
|
services:
|
||||||
|
gitSSH:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- address: "{{ .ContainerIp }}:{{ .SshPort }}"
|
29
internal/stacks/templates/gitea/entrypoint.sh
Normal file
29
internal/stacks/templates/gitea/entrypoint.sh
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
TRAEFIK_CONFIG_SRC="/helix/gitea/tmp/dynamic_git.yaml"
|
||||||
|
TRAEFIK_CONFIG_DEST="/helix/shared/traefik/dynamic/dynamic_git.yaml"
|
||||||
|
|
||||||
|
# Create the home directory.
|
||||||
|
if ! [ -d ${HOME} ]; then
|
||||||
|
mkdir -p ${HOME}
|
||||||
|
chmod 0700 ${HOME}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create the custom directory.
|
||||||
|
if ! [ -d ${GITEA_CUSTOM} ]; then
|
||||||
|
mkdir -p ${GITEA_CUSTOM}
|
||||||
|
chmod 0500 ${GITEA_CUSTOM}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Move the dynamic Traefik config to the shared volume.
|
||||||
|
if [ -f ${TRAEFIK_CONFIG_SRC} ]; then
|
||||||
|
mv ${TRAEFIK_CONFIG_SRC} ${TRAEFIK_CONFIG_DEST}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -gt 0 ]; then
|
||||||
|
exec "$@"
|
||||||
|
else
|
||||||
|
exec ${GITEA_BIN} -c ${GITEA_APP_INI} web
|
||||||
|
fi
|
|
@ -1,6 +1,6 @@
|
||||||
FROM traefik:{{ .Version }}
|
FROM traefik:{{ .Version }}
|
||||||
|
|
||||||
ADD traefik.yml /helix/traefik/
|
ADD traefik.yaml /helix/traefik/
|
||||||
|
|
||||||
ADD entrypoint.sh /
|
ADD entrypoint.sh /
|
||||||
|
|
||||||
|
@ -10,4 +10,4 @@ RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
EXPOSE 22 80 443
|
EXPOSE 22 80 443
|
||||||
|
|
||||||
CMD ["--configfile=/helix/traefik/traefik.yml"]
|
CMD ["--configfile=/helix/traefik/traefik.yaml"]
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
DASHBOARD_CONFIG_SRC="/tmp/dynamic_dashboard.yaml"
|
||||||
|
DASHBOARD_CONFIG_DEST="/helix/shared/traefik/dynamic/dashboard.yaml"
|
||||||
|
|
||||||
# Create the dynamic config directory in the shared volume.
|
# Create the dynamic config directory in the shared volume.
|
||||||
mkdir -p /helix/shared/traefik/dynamic
|
mkdir -p /helix/shared/traefik/dynamic
|
||||||
chgrp {{ .GroupId }} /helix/shared/traefik/dynamic
|
chgrp {{ .GroupId }} /helix/shared/traefik/dynamic
|
||||||
chmod a-rwx,u+rwx,g+rwx /helix/shared/traefik/dynamic
|
chmod a-rwx,u+rwx,g+rwx /helix/shared/traefik/dynamic
|
||||||
|
|
||||||
# Move the dashboard config to the new directory.
|
# Move the dashboard config to the new directory.
|
||||||
mv /tmp/dynamic_dashboard.yaml /helix/shared/traefik/dynamic/dashboard.yaml
|
if [ -f ${DASHBOARD_CONFIG_SRC} ]; then
|
||||||
|
mv ${DASHBOARD_CONFIG_SRC} ${DASHBOARD_CONFIG_DEST}
|
||||||
|
fi
|
||||||
|
|
||||||
# first arg is `-f` or `--some-option`
|
# first arg is `-f` or `--some-option`
|
||||||
if [ "${1#-}" != "$1" ]; then
|
if [ "${1#-}" != "$1" ]; then
|
||||||
|
|
Reference in a new issue