mirror of
https://git.evilfox.cc/test2/wg.git
synced 2026-07-31 20:03:22 +00:00
Add Go WireGuard panel with PostgreSQL 17 and Dokploy compose.
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/evilfox/wg-panel/internal/auth"
|
||||
"github.com/evilfox/wg-panel/internal/config"
|
||||
"github.com/evilfox/wg-panel/internal/db"
|
||||
"github.com/evilfox/wg-panel/internal/handlers"
|
||||
"github.com/evilfox/wg-panel/internal/mysqlimport"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg := config.Load()
|
||||
ctx := context.Background()
|
||||
|
||||
root := envOr("APP_ROOT", ".")
|
||||
migrationsDir := envOr("MIGRATIONS_DIR", filepath.Join(root, "migrations"))
|
||||
templatesDir := envOr("TEMPLATES_DIR", filepath.Join(root, "web", "templates"))
|
||||
staticDir := envOr("STATIC_DIR", filepath.Join(root, "web", "static"))
|
||||
|
||||
pool, err := waitForDB(ctx, cfg.DatabaseURL, 60*time.Second)
|
||||
if err != nil {
|
||||
log.Fatalf("database: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
if err := db.Migrate(ctx, pool, migrationsDir); err != nil {
|
||||
log.Fatalf("migrate: %v", err)
|
||||
}
|
||||
|
||||
if cfg.AutoImportDump {
|
||||
if _, err := os.Stat(cfg.MySQLDumpPath); err == nil {
|
||||
if err := mysqlimport.ImportFile(ctx, pool, cfg.MySQLDumpPath); err != nil {
|
||||
log.Fatalf("mysql import: %v", err)
|
||||
}
|
||||
} else {
|
||||
log.Printf("mysql dump not found at %s, skip import", cfg.MySQLDumpPath)
|
||||
}
|
||||
}
|
||||
|
||||
authStore := auth.NewStore(cfg, pool)
|
||||
if err := authStore.EnsureAdmin(ctx); err != nil {
|
||||
log.Fatalf("ensure admin: %v", err)
|
||||
}
|
||||
log.Printf("admin ready: username=%s email=%s", cfg.AdminUsername, cfg.AdminEmail)
|
||||
|
||||
app, err := handlers.New(pool, authStore, cfg, templatesDir)
|
||||
if err != nil {
|
||||
log.Fatalf("handlers: %v", err)
|
||||
}
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Use(middleware.RequestID)
|
||||
r.Use(middleware.RealIP)
|
||||
r.Use(middleware.Logger)
|
||||
r.Use(middleware.Recoverer)
|
||||
r.Use(app.OfflineMiddleware)
|
||||
|
||||
fileServer(r, "/static/", http.Dir(staticDir))
|
||||
|
||||
r.Get("/", app.Home)
|
||||
r.Get("/login", app.LoginPage)
|
||||
r.Post("/login", app.LoginPost)
|
||||
r.Get("/logout", app.Logout)
|
||||
r.Get("/wg", app.PublicWG)
|
||||
r.Get("/wg_config.php", app.PublicWG)
|
||||
|
||||
r.Route("/admin", func(r chi.Router) {
|
||||
r.Use(authStore.RequireAdmin)
|
||||
r.Get("/", app.AdminDashboard)
|
||||
r.Post("/status", app.AdminStatusPost)
|
||||
r.Get("/wg", app.AdminWG)
|
||||
r.Post("/wg/upload", app.AdminWGUpload)
|
||||
r.Post("/wg/delete", app.AdminWGDelete)
|
||||
r.Post("/wg/settings", app.AdminWGSettings)
|
||||
})
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: ":" + cfg.AppPort,
|
||||
Handler: r,
|
||||
ReadHeaderTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Printf("listening on :%s (%s)", cfg.AppPort, cfg.AppURL)
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("server: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-stop
|
||||
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
_ = srv.Shutdown(shutdownCtx)
|
||||
}
|
||||
|
||||
func waitForDB(ctx context.Context, databaseURL string, timeout time.Duration) (*pgxpool.Pool, error) {
|
||||
deadline := time.Now().Add(timeout)
|
||||
var last error
|
||||
for time.Now().Before(deadline) {
|
||||
pool, err := db.Connect(ctx, databaseURL)
|
||||
if err == nil {
|
||||
return pool, nil
|
||||
}
|
||||
last = err
|
||||
log.Printf("waiting for postgres: %v", err)
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
return nil, last
|
||||
}
|
||||
|
||||
func fileServer(r chi.Router, pathPrefix string, root http.FileSystem) {
|
||||
r.Handle(pathPrefix+"*", http.StripPrefix(pathPrefix, http.FileServer(root)))
|
||||
}
|
||||
|
||||
func envOr(k, def string) string {
|
||||
if v := os.Getenv(k); v != "" {
|
||||
return v
|
||||
}
|
||||
return def
|
||||
}
|
||||
Reference in New Issue
Block a user