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
22 changes: 20 additions & 2 deletions .drone.jsonnet
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
local name = 'mail';
local roundcube = '1.6.1';
local roundcube = '1.6.15';
local dovecot = '2.3.16';
local nginx = '1.24.0';
local postfix = '3.4.28';
local python = '3.12-slim-bookworm';
local golang = '1.24.0';
local node = '20';
local debian = 'bookworm-slim';
local bullseye = 'bullseye-slim';
local php = 'php:8.0.30-fpm-bullseye';
local postgres = 'postgres:9.4-alpine';
local platform = '26.04.10';
local playwright = 'mcr.microsoft.com/playwright:v1.48.2-jammy';
local mailpit = 'axllent/mailpit:latest';
local store_publisher = 'stable-303';
local distros = ['bookworm', 'buster'];

Expand Down Expand Up @@ -142,6 +144,13 @@ local build(arch, test_ui) = [{
'./cli/build.sh',
],
},
{
name: 'www',
image: 'node:' + node,
commands: [
'./www/build.sh',
],
},
{
name: 'package',
image: 'debian:' + debian,
Expand Down Expand Up @@ -226,7 +235,16 @@ local build(arch, test_ui) = [{
],
}
for distro in distros
],
] + (if test_ui then [
{
name: 'mailpit',
image: mailpit,
environment: {
MP_SMTP_AUTH_ACCEPT_ANY: '1',
MP_SMTP_AUTH_ALLOW_INSECURE: '1',
},
},
] else []),
volumes: [
{ name: 'dbus', host: { path: '/var/run/dbus' } },
{ name: 'dev', host: { path: '/dev' } },
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ log
lib
src/version
.drone.yml
.amd64watch.py
4 changes: 2 additions & 2 deletions bin/service.dovecot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ fi
export DOVECOT_BINDIR=${DIR}/dovecot/bin
case $1 in
start)
/bin/rm -rf ${SNAP_COMMON}/dovecot/master.pid
exec $DIR/dovecot/bin/dovecot.sh -F -c ${SNAP_COMMON}/config/dovecot/dovecot.conf
/bin/rm -rf ${SNAP_DATA}/dovecot/master.pid
exec $DIR/dovecot/bin/dovecot.sh -F -c ${SNAP_DATA}/config/dovecot/dovecot.conf
;;
*)
echo "not valid command"
Expand Down
2 changes: 1 addition & 1 deletion bin/service.nginx.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )

/bin/rm -f ${SNAP_COMMON}/web.socket
exec ${DIR}/nginx/bin/nginx.sh -c ${SNAP_COMMON}/config/nginx/nginx.conf -p ${DIR}/nginx -e stderr
exec ${DIR}/nginx/bin/nginx.sh -c ${SNAP_DATA}/config/nginx/nginx.conf -p ${DIR}/nginx -e stderr
2 changes: 1 addition & 1 deletion bin/service.opendkim.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fi

case $1 in
start)
exec $DIR/opendkim/bin/opendkim.sh -x ${SNAP_COMMON}/config/opendkim/opendkim.conf
exec $DIR/opendkim/bin/opendkim.sh -x ${SNAP_DATA}/config/opendkim/opendkim.conf
;;
*)
echo "not valid command"
Expand Down
4 changes: 2 additions & 2 deletions bin/service.php-fpm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ fi

case $1 in
start)
exec $DIR/php/bin/php-fpm.sh -y ${SNAP_COMMON}/config/php/php-fpm.conf -c ${SNAP_COMMON}/config/php/php.ini
exec $DIR/php/bin/php-fpm.sh -y ${SNAP_DATA}/config/php/php-fpm.conf -c ${SNAP_DATA}/config/php/php.ini
;;
post-start)
timeout 5 /bin/bash -c 'until [ -S '${SNAP_COMMON}'/log/php5-fpm.sock ]; do echo "waiting for ${SNAP_COMMON}/log/php5-fpm.sock"; sleep 1; done'
timeout 5 /bin/bash -c 'until [ -S '${SNAP_DATA}'/log/php5-fpm.sock ]; do echo "waiting for ${SNAP_DATA}/log/php5-fpm.sock"; sleep 1; done'
;;
*)
echo "not valid command"
Expand Down
4 changes: 2 additions & 2 deletions bin/service.postfix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ fi
case $1 in
start)
export SASL_PATH=$DIR/postfix/lib/sasl2
exec $DIR/postfix/bin/postfix.sh -c ${SNAP_COMMON}/config/postfix start
exec $DIR/postfix/bin/postfix.sh -c ${SNAP_DATA}/config/postfix start
;;
stop)
exec $DIR/postfix/bin/postfix.sh -c ${SNAP_COMMON}/config/postfix stop
exec $DIR/postfix/bin/postfix.sh -c ${SNAP_DATA}/config/postfix stop
;;
*)
echo "not valid command"
Expand Down
4 changes: 2 additions & 2 deletions bin/service.postgresql.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ fi

case $1 in
start)
exec ${DIR}/postgresql/bin/pg_ctl.sh -w -s -D ${SNAP_COMMON}/database start
exec ${DIR}/postgresql/bin/pg_ctl.sh -w -s -D ${SNAP_DATA}/database start
;;
stop)
exec ${DIR}/postgresql/bin/pg_ctl.sh -s -D ${SNAP_COMMON}/database stop -m fast
exec ${DIR}/postgresql/bin/pg_ctl.sh -s -D ${SNAP_DATA}/database stop -m fast
;;
*)
echo "not valid command"
Expand Down
3 changes: 3 additions & 0 deletions bin/service.webui.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
exec $DIR/webui unix ${SNAP_DATA}/webui.socket
1 change: 1 addition & 0 deletions cli/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ CGO_ENABLED=0 go build -buildvcs=false -o "$OUT_HOOKS/configure" ./cmd/config
CGO_ENABLED=0 go build -buildvcs=false -o "$OUT_HOOKS/pre-refresh" ./cmd/pre-refresh
CGO_ENABLED=0 go build -buildvcs=false -o "$OUT_HOOKS/post-refresh" ./cmd/post-refresh
CGO_ENABLED=0 go build -buildvcs=false -o "$OUT_BIN/cli" ./cmd/cli
CGO_ENABLED=0 go build -buildvcs=false -o "$OUT_BIN/webui" ./cmd/webui
34 changes: 34 additions & 0 deletions cli/cmd/webui/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package main

import (
"fmt"
"hooks/installer"
"hooks/rest"
"os"

"github.com/spf13/cobra"
"github.com/syncloud/golib/log"
)

func main() {
logger := log.Logger()

var rootCmd = &cobra.Command{
Use: "webui",
SilenceUsage: true,
}

rootCmd.AddCommand(&cobra.Command{
Use: "unix [socket]",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return rest.NewServer(installer.New(logger), args[0], logger).Start()
},
})

err := rootCmd.Execute()
if err != nil {
fmt.Print(err)
os.Exit(1)
}
}
7 changes: 7 additions & 0 deletions cli/installer/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ func (d *Database) Init() error {
if _, err := d.executor.RunDir("", "sudo", "-H", "-u", d.user, initdb, d.databaseDir); err != nil {
return err
}
return d.UpdateConfig()
}

func (d *Database) UpdateConfig() error {
if _, err := os.Stat(d.databaseDir); os.IsNotExist(err) {
return nil
}
src := path.Join(d.configDir, "postgresql", "postgresql.conf")
dst := path.Join(d.databaseDir, "postgresql.conf")
content, err := os.ReadFile(src)
Expand Down
64 changes: 62 additions & 2 deletions cli/installer/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ var dkimKeyPattern = regexp.MustCompile(`(?s).*p=(.*?)".*`)
type Variables struct {
AppDir string
AppDataDir string
AppCommonDir string
DbPsqlPath string
DbPsqlPort int
DbName string
Expand All @@ -44,6 +45,7 @@ type Variables struct {
type Installer struct {
appDir string
dataDir string
commonDir string
configPath string
logDir string
opendkimDir string
Expand All @@ -57,12 +59,14 @@ type Installer struct {

func New(logger *zap.Logger) *Installer {
appDir := fmt.Sprintf("/snap/%s/current", App)
dataDir := fmt.Sprintf("/var/snap/%s/common", App)
dataDir := fmt.Sprintf("/var/snap/%s/current", App)
commonDir := fmt.Sprintf("/var/snap/%s/common", App)
configPath := path.Join(dataDir, "config")
executor := NewExecutor(logger)
return &Installer{
appDir: appDir,
dataDir: dataDir,
commonDir: commonDir,
configPath: configPath,
logDir: path.Join(dataDir, "log"),
opendkimDir: path.Join(dataDir, "opendkim"),
Expand Down Expand Up @@ -100,10 +104,15 @@ func (i *Installer) RegenerateConfigs() error {
if err != nil {
return err
}
relay, err := i.GetRelay()
if err != nil {
return err
}

variables := Variables{
AppDir: i.appDir,
AppDataDir: i.dataDir,
AppCommonDir: i.commonDir,
DbPsqlPath: i.database.Dir(),
DbPsqlPort: i.database.Port(),
DbName: DbName,
Expand All @@ -120,10 +129,49 @@ func (i *Installer) RegenerateConfigs() error {
return err
}

if err := i.writeRelayMaps(relay, deviceDomainName); err != nil {
return err
}

return linux.Chown(i.configPath, UserName)
}

func (i *Installer) MigrateCommonToData() error {
marker := path.Join(i.dataDir, ".migrated_from_common")
if _, err := os.Stat(marker); err == nil {
return nil
}
if err := linux.CreateMissingDirs(i.dataDir); err != nil {
return err
}
entries, err := os.ReadDir(i.commonDir)
if err != nil {
if os.IsNotExist(err) {
return os.WriteFile(marker, []byte{}, 0644)
}
return err
}
for _, entry := range entries {
name := entry.Name()
if name == "web.socket" || strings.HasSuffix(name, ".socket") {
continue
}
dst := path.Join(i.dataDir, name)
if _, err := os.Stat(dst); err == nil {
continue
}
i.logger.Info("migrating to data", zap.String("name", name))
if err := os.Rename(path.Join(i.commonDir, name), dst); err != nil {
return err
}
}
return os.WriteFile(marker, []byte{}, 0644)
}

func (i *Installer) InitConfig() error {
if err := i.MigrateCommonToData(); err != nil {
return err
}
if err := linux.CreateUser("maildrop"); err != nil {
return err
}
Expand All @@ -142,6 +190,7 @@ func (i *Installer) InitConfig() error {
boxDataDir := path.Join(i.dataDir, "box")

if err := linux.CreateMissingDirs(
i.commonDir,
path.Join(i.dataDir, "nginx"),
path.Join(i.dataDir, "config"),
i.logDir,
Expand All @@ -161,6 +210,10 @@ func (i *Installer) InitConfig() error {
return err
}

if err := i.database.UpdateConfig(); err != nil {
return err
}

dkimKey, err := i.GenerateDkimKey(deviceDomainName, opendkimKeysDomainDir)
if err != nil {
return err
Expand All @@ -172,6 +225,9 @@ func (i *Installer) InitConfig() error {
if err := linux.Chown(i.dataDir, UserName); err != nil {
return err
}
if err := linux.Chown(i.commonDir, UserName); err != nil {
return err
}
if _, err := i.executor.RunDir("", "chown", "-R", "dovecot:dovecot", boxDataDir); err != nil {
return err
}
Expand Down Expand Up @@ -244,7 +300,11 @@ func (i *Installer) setActivated(activated bool) error {
return err
}
cfg.Section("mail").Key("activated").SetValue(strconv.FormatBool(activated))
return cfg.SaveTo(i.userConfigFile)
if err := cfg.SaveTo(i.userConfigFile); err != nil {
return err
}
_, err = i.executor.RunDir("", "chown", fmt.Sprintf("%s:%s", UserName, UserName), i.userConfigFile)
return err
}

func (i *Installer) PrepareStorage() error {
Expand Down
Loading