Skip to content
Merged
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
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ TIME KIND REMOTE SUMMARY
| --domain | OASTRIX_DOMAIN | localhost | Domain for token URLs |
| --http-port | OASTRIX_HTTP_PORT | 80 | HTTP capture port |
| --https-port | OASTRIX_HTTPS_PORT | 443 | HTTPS capture port |
| --api-port | OASTRIX_API_PORT | 8081 | API server port |
| --api-port | OASTRIX_API_PORT | 8443 | API server port (HTTPS only) |
| --dns-port | OASTRIX_DNS_PORT | 53 | DNS server port |
| --public-ip | OASTRIX_PUBLIC_IP | - | Public IP address of the server (see below) |
| --db | OASTRIX_DB | oastrix.db | SQLite database path |
Expand All @@ -112,7 +112,9 @@ TIME KIND REMOTE SUMMARY
|-------|----------|
| (default) | ACME enabled, automatic Let's Encrypt certs |
| --tls-cert + --tls-key | Manual TLS, uses provided certificates |
| --no-acme | No HTTPS server |
| --no-acme | No HTTPS or API server (HTTP/DNS only) |

**Note:** The API server requires TLS and is only available when HTTPS is enabled (either via ACME or manual certificates).

### Public IP

Expand All @@ -134,7 +136,7 @@ For development with `--no-acme`, this flag is optional.
| Flag | Env Var | Default | Description |
|------|---------|---------|-------------|
| --api-key | OASTRIX_API_KEY | - | API key (required) |
| --api-url | OASTRIX_API_URL | http://localhost:8081 | API server URL |
| --api-url | OASTRIX_API_URL | - | API server URL (required) |

## Production Deployment

Expand Down
5 changes: 4 additions & 1 deletion cmd/oastrix/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ type clientConfig struct {

func addClientFlags(cmd *cobra.Command, cfg *clientConfig) {
cmd.Flags().StringVar(&cfg.apiKey, "api-key", os.Getenv("OASTRIX_API_KEY"), "API key for authentication")
cmd.Flags().StringVar(&cfg.apiURL, "api-url", getEnv("OASTRIX_API_URL", "http://localhost:8081"), "API server URL")
cmd.Flags().StringVar(&cfg.apiURL, "api-url", os.Getenv("OASTRIX_API_URL"), "API server URL")
}

func (cfg *clientConfig) newClient() (*client.Client, error) {
if cfg.apiURL == "" {
return nil, fmt.Errorf("API URL required (use --api-url flag or OASTRIX_API_URL env var)")
}
if cfg.apiKey == "" {
return nil, fmt.Errorf("API key required (use --api-key flag or OASTRIX_API_KEY env var)")
}
Expand Down
52 changes: 31 additions & 21 deletions cmd/oastrix/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func init() {

serverCmd.Flags().IntVar(&serverFlags.httpPort, "http-port", getEnvInt("OASTRIX_HTTP_PORT", 80), "HTTP port to listen on")
serverCmd.Flags().IntVar(&serverFlags.httpsPort, "https-port", getEnvInt("OASTRIX_HTTPS_PORT", 443), "HTTPS port to listen on")
serverCmd.Flags().IntVar(&serverFlags.apiPort, "api-port", getEnvInt("OASTRIX_API_PORT", 8081), "API port to listen on")
serverCmd.Flags().IntVar(&serverFlags.apiPort, "api-port", getEnvInt("OASTRIX_API_PORT", 8443), "API port to listen on")
serverCmd.Flags().IntVar(&serverFlags.dnsPort, "dns-port", getEnvInt("OASTRIX_DNS_PORT", 53), "DNS port to listen on (53 requires root)")
serverCmd.Flags().StringVar(&serverFlags.tlsCert, "tls-cert", "", "path to TLS certificate file (enables manual TLS mode)")
serverCmd.Flags().StringVar(&serverFlags.tlsKey, "tls-key", "", "path to TLS key file (enables manual TLS mode)")
Expand Down Expand Up @@ -144,23 +144,6 @@ func runServer(cmd *cobra.Command, args []string) error {
return fmt.Errorf("http server: %w", err)
}

apiSrv := &server.APIServer{
DB: database,
Domain: serverFlags.domain,
PublicIP: serverFlags.publicIP,
Logger: logger.Named("api"),
}

apiLogger := logger.Named("api")
apiCfg := server.DefaultServerConfig(fmt.Sprintf(":%d", serverFlags.apiPort), apiSrv.Handler(), apiLogger)
apiServer := server.NewManagedServer("api", apiCfg)

logger.Info("starting api server", logging.Port(serverFlags.apiPort))
apiServer.Start()
if err := apiServer.WaitForStartup(100 * time.Millisecond); err != nil {
return fmt.Errorf("api server: %w", err)
}

dnsSrv := &server.DNSServer{
Pipeline: pipeline,
Domain: serverFlags.domain,
Expand All @@ -173,6 +156,8 @@ func runServer(cmd *cobra.Command, args []string) error {
}

var httpsServer *server.ManagedServer
var apiServer *server.ManagedServer
var tlsConfig *tls.Config
acmeCtx, acmeCancel := context.WithCancel(context.Background())
defer acmeCancel()

Expand All @@ -185,8 +170,10 @@ func runServer(cmd *cobra.Command, args []string) error {
return fmt.Errorf("start ACME certificate management: %w", err)
}

tlsConfig = acmeManager.TLSConfig()

httpsCfg := server.DefaultServerConfig(fmt.Sprintf(":%d", serverFlags.httpsPort), httpSrv, httpsLogger)
httpsCfg.TLSConfig = acmeManager.TLSConfig()
httpsCfg.TLSConfig = tlsConfig
httpsServer = server.NewManagedServer("https", httpsCfg)

logger.Info("starting https server", logging.Port(serverFlags.httpsPort), logging.TLSMode("acme"))
Expand All @@ -205,7 +192,7 @@ func runServer(cmd *cobra.Command, args []string) error {
return fmt.Errorf("load TLS certificate: %w", err)
}

tlsConfig := &tls.Config{
tlsConfig = &tls.Config{
Certificates: []tls.Certificate{cert},
}

Expand All @@ -222,6 +209,27 @@ func runServer(cmd *cobra.Command, args []string) error {
logger.Info("https disabled", zap.String("reason", "no-acme specified without manual TLS certificates"))
}

apiSrv := &server.APIServer{
DB: database,
Domain: serverFlags.domain,
PublicIP: serverFlags.publicIP,
Logger: logger.Named("api"),
}
apiLogger := logger.Named("api")
apiCfg := server.DefaultServerConfig(fmt.Sprintf(":%d", serverFlags.apiPort), apiSrv.Handler(), apiLogger)

if tlsConfig != nil {
apiCfg.TLSConfig = tlsConfig
apiServer = server.NewManagedServer("api", apiCfg)
logger.Info("starting api server", logging.Port(serverFlags.apiPort), logging.TLSMode("https"))
apiServer.Start()
if err := apiServer.WaitForStartup(100 * time.Millisecond); err != nil {
return fmt.Errorf("api server: %w", err)
}
} else {
logger.Warn("api server disabled", zap.String("reason", "TLS required but not configured"))
}

sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
<-sigCh
Expand All @@ -235,7 +243,9 @@ func runServer(cmd *cobra.Command, args []string) error {
httpsServer.Shutdown(ctx)
}
httpServer.Shutdown(ctx)
apiServer.Shutdown(ctx)
if apiServer != nil {
apiServer.Shutdown(ctx)
}
dnsSrv.Shutdown(ctx)

return nil
Expand Down