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
6 changes: 6 additions & 0 deletions cmd/outpost-migrate-redis/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ func NewCommand() *cli.Command {
Usage: "Redis server port (overrides config)",
Sources: cli.EnvVars("REDIS_PORT"),
},
&cli.StringFlag{
Name: "redis-username",
Usage: "Redis username for ACL authentication (overrides config)",
Sources: cli.EnvVars("REDIS_USERNAME"),
},
&cli.StringFlag{
Name: "redis-password",
Usage: "Redis password (overrides config)",
Expand Down Expand Up @@ -202,6 +207,7 @@ func withMigrator(ctx context.Context, c *cli.Command, fn func(*Migrator) error)
rc.Database,
rc.ClusterEnabled,
rc.TLSEnabled,
rc.Username != "",
rc.Password != "",
)

Expand Down
4 changes: 4 additions & 0 deletions cmd/outpost-migrate-redis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ func (cl *ConfigLoader) applyRedisOverrides(c *cli.Command, cfg *config.Config)
cfg.Redis.Port = port
}

if username := c.String("redis-username"); username != "" {
cfg.Redis.Username = username
}

if password := c.String("redis-password"); password != "" {
cfg.Redis.Password = password
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/outpost-migrate-redis/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type MigrationLogger interface {
Verbose() bool

// Configuration and initialization
LogRedisConfig(host string, port int, database int, clusterEnabled bool, tlsEnabled bool, hasPassword bool)
LogRedisConfig(host string, port int, database int, clusterEnabled bool, tlsEnabled bool, hasUsername bool, hasPassword bool)
LogInitialization(isFresh bool, migrationsMarked int)

// Migration lifecycle
Expand Down
7 changes: 6 additions & 1 deletion cmd/outpost-migrate-redis/logger_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (l *CLILogger) Verbose() bool {
}

// Configuration and initialization
func (l *CLILogger) LogRedisConfig(host string, port int, database int, clusterEnabled bool, tlsEnabled bool, hasPassword bool) {
func (l *CLILogger) LogRedisConfig(host string, port int, database int, clusterEnabled bool, tlsEnabled bool, hasUsername bool, hasPassword bool) {
if !l.verbose {
return
}
Expand All @@ -38,6 +38,11 @@ func (l *CLILogger) LogRedisConfig(host string, port int, database int, clusterE
fmt.Printf(" Database: %d\n", database)
fmt.Printf(" Cluster Enabled: %v\n", clusterEnabled)
fmt.Printf(" TLS Enabled: %v\n", tlsEnabled)
if hasUsername {
fmt.Printf(" Username: ****** (set)\n")
} else {
fmt.Printf(" Username: (not set)\n")
}
if hasPassword {
fmt.Printf(" Password: ****** (set)\n")
} else {
Expand Down
3 changes: 2 additions & 1 deletion cmd/outpost-migrate-redis/logger_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (l *ServerLogger) Verbose() bool {
}

// Configuration and initialization
func (l *ServerLogger) LogRedisConfig(host string, port int, database int, clusterEnabled bool, tlsEnabled bool, hasPassword bool) {
func (l *ServerLogger) LogRedisConfig(host string, port int, database int, clusterEnabled bool, tlsEnabled bool, hasUsername bool, hasPassword bool) {
if !l.verbose {
return
}
Expand All @@ -39,6 +39,7 @@ func (l *ServerLogger) LogRedisConfig(host string, port int, database int, clust
zap.Int("database", database),
zap.Bool("cluster_enabled", clusterEnabled),
zap.Bool("tls_enabled", tlsEnabled),
zap.Bool("username_set", hasUsername),
zap.Bool("password_set", hasPassword),
)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/outpost-migrate-redis/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func newMockLogger() *mockLogger {
}

func (l *mockLogger) Verbose() bool { return false }
func (l *mockLogger) LogRedisConfig(string, int, int, bool, bool, bool) {}
func (l *mockLogger) LogRedisConfig(string, int, int, bool, bool, bool, bool) {}
func (l *mockLogger) LogInitialization(bool, int) {}
func (l *mockLogger) LogMigrationList(map[string]string) {}
func (l *mockLogger) LogMigrationStatus(int, int) {}
Expand Down
25 changes: 23 additions & 2 deletions docs/pages/references/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Global configurations are provided through env variables or a YAML file. ConfigM
| `AZURE_SERVICEBUS_RESOURCE_GROUP` | Azure resource group name | `nil` | Yes |
| `AZURE_SERVICEBUS_SUBSCRIPTION_ID` | Azure subscription ID | `nil` | Yes |
| `AZURE_SERVICEBUS_TENANT_ID` | Azure Active Directory tenant ID | `nil` | Yes |
| `CLICKHOUSE_ADDR` | Address (host:port) of the ClickHouse server. Example: 'localhost:9000'. | `nil` | No |
| `CLICKHOUSE_DATABASE` | Database name in ClickHouse to use. | `outpost` | No |
| `CLICKHOUSE_PASSWORD` | Password for ClickHouse authentication. | `nil` | No |
| `CLICKHOUSE_USERNAME` | Username for ClickHouse authentication. | `nil` | No |
| `DELIVERY_IDEMPOTENCY_KEY_TTL` | Time-to-live in seconds for delivery queue idempotency keys. Controls how long processed deliveries are remembered to prevent duplicate delivery attempts. Default: 3600 (1 hour). | `3600` | No |
| `DELIVERY_MAX_CONCURRENCY` | Maximum number of delivery attempts to process concurrently. | `1` | No |
| `DELIVERY_TIMEOUT_SECONDS` | Timeout in seconds for HTTP requests made during event delivery to webhook destinations. | `5` | No |
Expand Down Expand Up @@ -96,7 +100,7 @@ Global configurations are provided through env variables or a YAML file. ConfigM
| `PORTAL_ORGANIZATION_NAME` | Organization name displayed in the Outpost Portal. | `nil` | No |
| `PORTAL_PROXY_URL` | URL to proxy the Outpost Portal through. If set, Outpost serves the portal assets, and this URL is used as the base. Must be a valid URL. | `nil` | No |
| `PORTAL_REFERER_URL` | The URL where the user is redirected when the JWT token is expired or when the user clicks 'back'. Required if the Outpost Portal is enabled/used. | `nil` | Conditional |
| `POSTGRES_URL` | Connection URL for PostgreSQL, used for log storage. Example: 'postgres://user:pass@host:port/dbname?sslmode=disable'. | `nil` | Yes |
| `POSTGRES_URL` | Connection URL for PostgreSQL, used for log storage. Example: 'postgres://user:pass@host:port/dbname?sslmode=disable'. | `nil` | No |
| `PUBLISH_AWS_SQS_ACCESS_KEY_ID` | AWS Access Key ID for the SQS publish queue. Required if AWS SQS is the chosen publish MQ provider. | `nil` | Conditional |
| `PUBLISH_AWS_SQS_ENDPOINT` | Custom AWS SQS endpoint URL for the publish queue. Optional. | `nil` | No |
| `PUBLISH_AWS_SQS_QUEUE` | Name of the SQS queue for publishing events. Required if AWS SQS is the chosen publish MQ provider. | `nil` | Conditional |
Expand Down Expand Up @@ -125,6 +129,7 @@ Global configurations are provided through env variables or a YAML file. ConfigM
| `REDIS_PASSWORD` | Password for Redis authentication, if required by the server. | `nil` | Yes |
| `REDIS_PORT` | Port number for the Redis server. | `6379` | Yes |
| `REDIS_TLS_ENABLED` | Enable TLS encryption for Redis connection. | `false` | No |
| `REDIS_USERNAME` | Username for Redis ACL authentication. | `nil` | No |
| `RETRY_INTERVAL_SECONDS` | Interval in seconds for exponential backoff retry strategy (base 2). Ignored if retry_schedule is provided. | `30` | No |
| `RETRY_POLL_BACKOFF_MS` | Backoff time in milliseconds when the retry monitor finds no messages to process. When a retry message is found, the monitor immediately polls for the next message without delay. Lower values provide faster retry processing but increase Redis load. For serverless Redis providers (Upstash, ElastiCache Serverless), consider increasing to 5000-10000ms to reduce costs. Default: 100 | `100` | No |
| `RETRY_SCHEDULE` | Comma-separated list of retry delays in seconds. If provided, overrides retry_interval_seconds and retry_max_limit. Schedule length defines the max number of retries. Example: '5,60,600,3600,7200' for 5 retries at 5s, 1m, 10m, 1h, 2h. | `[]` | No |
Expand Down Expand Up @@ -172,6 +177,20 @@ alert:
# Enables or disables audit logging for significant events.
audit_log: true

clickhouse:
# Address (host:port) of the ClickHouse server. Example: 'localhost:9000'.
addr: ""

# Database name in ClickHouse to use.
database: "outpost"

# Password for ClickHouse authentication.
password: ""

# Username for ClickHouse authentication.
username: ""


# Time-to-live in seconds for delivery queue idempotency keys. Controls how long processed deliveries are remembered to prevent duplicate delivery attempts. Default: 3600 (1 hour).
delivery_idempotency_key_ttl: 3600

Expand Down Expand Up @@ -466,7 +485,6 @@ portal:


# Connection URL for PostgreSQL, used for log storage. Example: 'postgres://user:pass@host:port/dbname?sslmode=disable'.
# Required: Y
postgres: ""

# Time-to-live in seconds for publish queue idempotency keys. Controls how long processed events are remembered to prevent duplicate processing. Default: 3600 (1 hour).
Expand Down Expand Up @@ -573,6 +591,9 @@ redis:
# Enable TLS encryption for Redis connection.
tls_enabled: false

# Username for Redis ACL authentication.
username: ""


# Interval in seconds for exponential backoff retry strategy (base 2). Ignored if retry_schedule is provided.
retry_interval_seconds: 30
Expand Down
1 change: 1 addition & 0 deletions examples/docker-compose/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ AES_ENCRYPTION_SECRET="encryptionsecret"
# Redis
REDIS_HOST="redis"
REDIS_PORT="6379"
REDIS_USERNAME=""
REDIS_PASSWORD="password"
REDIS_DATABASE="0"
2 changes: 2 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ func ParseWithOS(flags Flags, osInterface OSInterface) (*Config, error) {
type RedisConfig struct {
Host string `yaml:"host" env:"REDIS_HOST" desc:"Hostname or IP address of the Redis server." required:"Y"`
Port int `yaml:"port" env:"REDIS_PORT" desc:"Port number for the Redis server." required:"Y"`
Username string `yaml:"username" env:"REDIS_USERNAME" desc:"Username for Redis ACL authentication." required:"N"`
Password string `yaml:"password" env:"REDIS_PASSWORD" desc:"Password for Redis authentication, if required by the server." required:"Y"`
Database int `yaml:"database" env:"REDIS_DATABASE" desc:"Redis database number to select after connecting (ignored in cluster mode)." required:"Y"`
TLSEnabled bool `yaml:"tls_enabled" env:"REDIS_TLS_ENABLED" desc:"Enable TLS encryption for Redis connection." required:"N"`
Expand All @@ -371,6 +372,7 @@ func (c *RedisConfig) ToConfig() *redis.RedisConfig {
return &redis.RedisConfig{
Host: c.Host,
Port: c.Port,
Username: c.Username,
Password: c.Password,
Database: c.Database,
TLSEnabled: c.TLSEnabled,
Expand Down
1 change: 1 addition & 0 deletions internal/redis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package redis
type RedisConfig struct {
Host string
Port int
Username string
Password string
Database int
TLSEnabled bool
Expand Down
2 changes: 2 additions & 0 deletions internal/redis/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func createClusterClient(ctx context.Context, config *RedisConfig) (Client, erro
// Start with single node - cluster client will auto-discover other nodes
options := &r.ClusterOptions{
Addrs: []string{fmt.Sprintf("%s:%d", config.Host, config.Port)},
Username: config.Username,
Password: config.Password,
// Note: Database is ignored in cluster mode
}
Expand Down Expand Up @@ -103,6 +104,7 @@ func createClusterClient(ctx context.Context, config *RedisConfig) (Client, erro
func createRegularClient(ctx context.Context, config *RedisConfig) (Client, error) {
options := &r.Options{
Addr: fmt.Sprintf("%s:%d", config.Host, config.Port),
Username: config.Username,
Password: config.Password,
DB: config.Database,
}
Expand Down