Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
f2e20670
"frontend/src/git@web.lueluesay.top:chenxi/sub2api.git" did not exist on "f7fa71bc2807c9863eaa8a996355f14d9c9f4f79"
Commit
f2e20670
authored
Jan 31, 2026
by
iBenzene
Browse files
feat: add support for using TLS to connect to Redis
parent
c3d1891c
Changes
15
Hide whitespace changes
Inline
Side-by-side
backend/internal/config/config.go
View file @
f2e20670
...
@@ -415,6 +415,8 @@ type RedisConfig struct {
...
@@ -415,6 +415,8 @@ type RedisConfig struct {
PoolSize
int
`mapstructure:"pool_size"`
PoolSize
int
`mapstructure:"pool_size"`
// MinIdleConns: 最小空闲连接数,保持热连接减少冷启动延迟
// MinIdleConns: 最小空闲连接数,保持热连接减少冷启动延迟
MinIdleConns
int
`mapstructure:"min_idle_conns"`
MinIdleConns
int
`mapstructure:"min_idle_conns"`
// EnableTLS: 是否启用 TLS/SSL 连接
EnableTLS
bool
`mapstructure:"enable_tls"`
}
}
func
(
r
*
RedisConfig
)
Address
()
string
{
func
(
r
*
RedisConfig
)
Address
()
string
{
...
@@ -762,6 +764,7 @@ func setDefaults() {
...
@@ -762,6 +764,7 @@ func setDefaults() {
viper
.
SetDefault
(
"redis.write_timeout_seconds"
,
3
)
viper
.
SetDefault
(
"redis.write_timeout_seconds"
,
3
)
viper
.
SetDefault
(
"redis.pool_size"
,
128
)
viper
.
SetDefault
(
"redis.pool_size"
,
128
)
viper
.
SetDefault
(
"redis.min_idle_conns"
,
10
)
viper
.
SetDefault
(
"redis.min_idle_conns"
,
10
)
viper
.
SetDefault
(
"redis.enable_tls"
,
false
)
// Ops (vNext)
// Ops (vNext)
viper
.
SetDefault
(
"ops.enabled"
,
true
)
viper
.
SetDefault
(
"ops.enabled"
,
true
)
...
...
backend/internal/repository/redis.go
View file @
f2e20670
package
repository
package
repository
import
(
import
(
"crypto/tls"
"time"
"time"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/config"
...
@@ -26,7 +27,7 @@ func InitRedis(cfg *config.Config) *redis.Client {
...
@@ -26,7 +27,7 @@ func InitRedis(cfg *config.Config) *redis.Client {
// buildRedisOptions 构建 Redis 连接选项
// buildRedisOptions 构建 Redis 连接选项
// 从配置文件读取连接池和超时参数,支持生产环境调优
// 从配置文件读取连接池和超时参数,支持生产环境调优
func
buildRedisOptions
(
cfg
*
config
.
Config
)
*
redis
.
Options
{
func
buildRedisOptions
(
cfg
*
config
.
Config
)
*
redis
.
Options
{
return
&
redis
.
Options
{
opts
:=
&
redis
.
Options
{
Addr
:
cfg
.
Redis
.
Address
(),
Addr
:
cfg
.
Redis
.
Address
(),
Password
:
cfg
.
Redis
.
Password
,
Password
:
cfg
.
Redis
.
Password
,
DB
:
cfg
.
Redis
.
DB
,
DB
:
cfg
.
Redis
.
DB
,
...
@@ -36,4 +37,13 @@ func buildRedisOptions(cfg *config.Config) *redis.Options {
...
@@ -36,4 +37,13 @@ func buildRedisOptions(cfg *config.Config) *redis.Options {
PoolSize
:
cfg
.
Redis
.
PoolSize
,
// 连接池大小
PoolSize
:
cfg
.
Redis
.
PoolSize
,
// 连接池大小
MinIdleConns
:
cfg
.
Redis
.
MinIdleConns
,
// 最小空闲连接
MinIdleConns
:
cfg
.
Redis
.
MinIdleConns
,
// 最小空闲连接
}
}
if
cfg
.
Redis
.
EnableTLS
{
opts
.
TLSConfig
=
&
tls
.
Config
{
MinVersion
:
tls
.
VersionTLS12
,
ServerName
:
cfg
.
Redis
.
Host
,
}
}
return
opts
}
}
backend/internal/repository/redis_test.go
View file @
f2e20670
...
@@ -32,4 +32,16 @@ func TestBuildRedisOptions(t *testing.T) {
...
@@ -32,4 +32,16 @@ func TestBuildRedisOptions(t *testing.T) {
require
.
Equal
(
t
,
4
*
time
.
Second
,
opts
.
WriteTimeout
)
require
.
Equal
(
t
,
4
*
time
.
Second
,
opts
.
WriteTimeout
)
require
.
Equal
(
t
,
100
,
opts
.
PoolSize
)
require
.
Equal
(
t
,
100
,
opts
.
PoolSize
)
require
.
Equal
(
t
,
10
,
opts
.
MinIdleConns
)
require
.
Equal
(
t
,
10
,
opts
.
MinIdleConns
)
require
.
Nil
(
t
,
opts
.
TLSConfig
)
// Test case with TLS enabled
cfgTLS
:=
&
config
.
Config
{
Redis
:
config
.
RedisConfig
{
Host
:
"localhost"
,
EnableTLS
:
true
,
},
}
optsTLS
:=
buildRedisOptions
(
cfgTLS
)
require
.
NotNil
(
t
,
optsTLS
.
TLSConfig
)
require
.
Equal
(
t
,
"localhost"
,
optsTLS
.
TLSConfig
.
ServerName
)
}
}
backend/internal/setup/cli.go
View file @
f2e20670
...
@@ -149,6 +149,8 @@ func RunCLI() error {
...
@@ -149,6 +149,8 @@ func RunCLI() error {
fmt
.
Println
(
" Invalid Redis DB. Must be between 0 and 15."
)
fmt
.
Println
(
" Invalid Redis DB. Must be between 0 and 15."
)
}
}
cfg
.
Redis
.
EnableTLS
=
promptConfirm
(
reader
,
"Enable Redis TLS?"
)
fmt
.
Println
()
fmt
.
Println
()
fmt
.
Print
(
"Testing Redis connection... "
)
fmt
.
Print
(
"Testing Redis connection... "
)
if
err
:=
TestRedisConnection
(
&
cfg
.
Redis
);
err
!=
nil
{
if
err
:=
TestRedisConnection
(
&
cfg
.
Redis
);
err
!=
nil
{
...
@@ -205,6 +207,7 @@ func RunCLI() error {
...
@@ -205,6 +207,7 @@ func RunCLI() error {
fmt
.
Println
(
"── Configuration Summary ──"
)
fmt
.
Println
(
"── Configuration Summary ──"
)
fmt
.
Printf
(
"Database: %s@%s:%d/%s
\n
"
,
cfg
.
Database
.
User
,
cfg
.
Database
.
Host
,
cfg
.
Database
.
Port
,
cfg
.
Database
.
DBName
)
fmt
.
Printf
(
"Database: %s@%s:%d/%s
\n
"
,
cfg
.
Database
.
User
,
cfg
.
Database
.
Host
,
cfg
.
Database
.
Port
,
cfg
.
Database
.
DBName
)
fmt
.
Printf
(
"Redis: %s:%d
\n
"
,
cfg
.
Redis
.
Host
,
cfg
.
Redis
.
Port
)
fmt
.
Printf
(
"Redis: %s:%d
\n
"
,
cfg
.
Redis
.
Host
,
cfg
.
Redis
.
Port
)
fmt
.
Printf
(
"Redis TLS: %s
\n
"
,
map
[
bool
]
string
{
true
:
"enabled"
,
false
:
"disabled"
}[
cfg
.
Redis
.
EnableTLS
])
fmt
.
Printf
(
"Admin: %s
\n
"
,
cfg
.
Admin
.
Email
)
fmt
.
Printf
(
"Admin: %s
\n
"
,
cfg
.
Admin
.
Email
)
fmt
.
Printf
(
"Server: :%d
\n
"
,
cfg
.
Server
.
Port
)
fmt
.
Printf
(
"Server: :%d
\n
"
,
cfg
.
Server
.
Port
)
fmt
.
Println
()
fmt
.
Println
()
...
...
backend/internal/setup/handler.go
View file @
f2e20670
...
@@ -176,10 +176,11 @@ func testDatabase(c *gin.Context) {
...
@@ -176,10 +176,11 @@ func testDatabase(c *gin.Context) {
// TestRedisRequest represents Redis test request
// TestRedisRequest represents Redis test request
type
TestRedisRequest
struct
{
type
TestRedisRequest
struct
{
Host
string
`json:"host" binding:"required"`
Host
string
`json:"host" binding:"required"`
Port
int
`json:"port" binding:"required"`
Port
int
`json:"port" binding:"required"`
Password
string
`json:"password"`
Password
string
`json:"password"`
DB
int
`json:"db"`
DB
int
`json:"db"`
EnableTLS
bool
`json:"enable_tls"`
}
}
// testRedis tests Redis connection
// testRedis tests Redis connection
...
@@ -205,10 +206,11 @@ func testRedis(c *gin.Context) {
...
@@ -205,10 +206,11 @@ func testRedis(c *gin.Context) {
}
}
cfg
:=
&
RedisConfig
{
cfg
:=
&
RedisConfig
{
Host
:
req
.
Host
,
Host
:
req
.
Host
,
Port
:
req
.
Port
,
Port
:
req
.
Port
,
Password
:
req
.
Password
,
Password
:
req
.
Password
,
DB
:
req
.
DB
,
DB
:
req
.
DB
,
EnableTLS
:
req
.
EnableTLS
,
}
}
if
err
:=
TestRedisConnection
(
cfg
);
err
!=
nil
{
if
err
:=
TestRedisConnection
(
cfg
);
err
!=
nil
{
...
...
backend/internal/setup/setup.go
View file @
f2e20670
...
@@ -3,6 +3,7 @@ package setup
...
@@ -3,6 +3,7 @@ package setup
import
(
import
(
"context"
"context"
"crypto/rand"
"crypto/rand"
"crypto/tls"
"database/sql"
"database/sql"
"encoding/hex"
"encoding/hex"
"fmt"
"fmt"
...
@@ -79,10 +80,11 @@ type DatabaseConfig struct {
...
@@ -79,10 +80,11 @@ type DatabaseConfig struct {
}
}
type
RedisConfig
struct
{
type
RedisConfig
struct
{
Host
string
`json:"host" yaml:"host"`
Host
string
`json:"host" yaml:"host"`
Port
int
`json:"port" yaml:"port"`
Port
int
`json:"port" yaml:"port"`
Password
string
`json:"password" yaml:"password"`
Password
string
`json:"password" yaml:"password"`
DB
int
`json:"db" yaml:"db"`
DB
int
`json:"db" yaml:"db"`
EnableTLS
bool
`json:"enable_tls" yaml:"enable_tls"`
}
}
type
AdminConfig
struct
{
type
AdminConfig
struct
{
...
@@ -199,11 +201,20 @@ func TestDatabaseConnection(cfg *DatabaseConfig) error {
...
@@ -199,11 +201,20 @@ func TestDatabaseConnection(cfg *DatabaseConfig) error {
// TestRedisConnection tests the Redis connection
// TestRedisConnection tests the Redis connection
func
TestRedisConnection
(
cfg
*
RedisConfig
)
error
{
func
TestRedisConnection
(
cfg
*
RedisConfig
)
error
{
rdb
:=
redis
.
NewClient
(
&
redis
.
Options
{
opts
:=
&
redis
.
Options
{
Addr
:
fmt
.
Sprintf
(
"%s:%d"
,
cfg
.
Host
,
cfg
.
Port
),
Addr
:
fmt
.
Sprintf
(
"%s:%d"
,
cfg
.
Host
,
cfg
.
Port
),
Password
:
cfg
.
Password
,
Password
:
cfg
.
Password
,
DB
:
cfg
.
DB
,
DB
:
cfg
.
DB
,
})
}
if
cfg
.
EnableTLS
{
opts
.
TLSConfig
=
&
tls
.
Config
{
MinVersion
:
tls
.
VersionTLS12
,
ServerName
:
cfg
.
Host
,
}
}
rdb
:=
redis
.
NewClient
(
opts
)
defer
func
()
{
defer
func
()
{
if
err
:=
rdb
.
Close
();
err
!=
nil
{
if
err
:=
rdb
.
Close
();
err
!=
nil
{
log
.
Printf
(
"failed to close redis client: %v"
,
err
)
log
.
Printf
(
"failed to close redis client: %v"
,
err
)
...
@@ -485,10 +496,11 @@ func AutoSetupFromEnv() error {
...
@@ -485,10 +496,11 @@ func AutoSetupFromEnv() error {
SSLMode
:
getEnvOrDefault
(
"DATABASE_SSLMODE"
,
"disable"
),
SSLMode
:
getEnvOrDefault
(
"DATABASE_SSLMODE"
,
"disable"
),
},
},
Redis
:
RedisConfig
{
Redis
:
RedisConfig
{
Host
:
getEnvOrDefault
(
"REDIS_HOST"
,
"localhost"
),
Host
:
getEnvOrDefault
(
"REDIS_HOST"
,
"localhost"
),
Port
:
getEnvIntOrDefault
(
"REDIS_PORT"
,
6379
),
Port
:
getEnvIntOrDefault
(
"REDIS_PORT"
,
6379
),
Password
:
getEnvOrDefault
(
"REDIS_PASSWORD"
,
""
),
Password
:
getEnvOrDefault
(
"REDIS_PASSWORD"
,
""
),
DB
:
getEnvIntOrDefault
(
"REDIS_DB"
,
0
),
DB
:
getEnvIntOrDefault
(
"REDIS_DB"
,
0
),
EnableTLS
:
getEnvOrDefault
(
"REDIS_ENABLE_TLS"
,
"false"
)
==
"true"
,
},
},
Admin
:
AdminConfig
{
Admin
:
AdminConfig
{
Email
:
getEnvOrDefault
(
"ADMIN_EMAIL"
,
"admin@sub2api.local"
),
Email
:
getEnvOrDefault
(
"ADMIN_EMAIL"
,
"admin@sub2api.local"
),
...
...
config.yaml
View file @
f2e20670
...
@@ -322,6 +322,9 @@ redis:
...
@@ -322,6 +322,9 @@ redis:
# Database number (0-15)
# Database number (0-15)
# 数据库编号(0-15)
# 数据库编号(0-15)
db
:
0
db
:
0
# Enable TLS/SSL connection
# 是否启用 TLS/SSL 连接
enable_tls
:
false
# =============================================================================
# =============================================================================
# Ops Monitoring (Optional)
# Ops Monitoring (Optional)
...
...
deploy/.env.example
View file @
f2e20670
...
@@ -40,6 +40,7 @@ POSTGRES_DB=sub2api
...
@@ -40,6 +40,7 @@ POSTGRES_DB=sub2api
# Leave empty for no password (default for local development)
# Leave empty for no password (default for local development)
REDIS_PASSWORD=
REDIS_PASSWORD=
REDIS_DB=0
REDIS_DB=0
REDIS_ENABLE_TLS=false
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Admin Account
# Admin Account
...
...
deploy/config.example.yaml
View file @
f2e20670
...
@@ -376,6 +376,9 @@ redis:
...
@@ -376,6 +376,9 @@ redis:
# Database number (0-15)
# Database number (0-15)
# 数据库编号(0-15)
# 数据库编号(0-15)
db
:
0
db
:
0
# Enable TLS/SSL connection
# 是否启用 TLS/SSL 连接
enable_tls
:
false
# =============================================================================
# =============================================================================
# Ops Monitoring (Optional)
# Ops Monitoring (Optional)
...
...
deploy/docker-compose.standalone.yml
View file @
f2e20670
...
@@ -56,6 +56,7 @@ services:
...
@@ -56,6 +56,7 @@ services:
-
REDIS_PORT=${REDIS_PORT:-6379}
-
REDIS_PORT=${REDIS_PORT:-6379}
-
REDIS_PASSWORD=${REDIS_PASSWORD:-}
-
REDIS_PASSWORD=${REDIS_PASSWORD:-}
-
REDIS_DB=${REDIS_DB:-0}
-
REDIS_DB=${REDIS_DB:-0}
-
REDIS_ENABLE_TLS=${REDIS_ENABLE_TLS:-false}
# =======================================================================
# =======================================================================
# Admin Account (auto-created on first run)
# Admin Account (auto-created on first run)
...
...
deploy/docker-compose.yml
View file @
f2e20670
...
@@ -62,6 +62,7 @@ services:
...
@@ -62,6 +62,7 @@ services:
-
REDIS_PORT=6379
-
REDIS_PORT=6379
-
REDIS_PASSWORD=${REDIS_PASSWORD:-}
-
REDIS_PASSWORD=${REDIS_PASSWORD:-}
-
REDIS_DB=${REDIS_DB:-0}
-
REDIS_DB=${REDIS_DB:-0}
-
REDIS_ENABLE_TLS=${REDIS_ENABLE_TLS:-false}
# =======================================================================
# =======================================================================
# Admin Account (auto-created on first run)
# Admin Account (auto-created on first run)
...
...
frontend/src/api/setup.ts
View file @
f2e20670
...
@@ -31,6 +31,7 @@ export interface RedisConfig {
...
@@ -31,6 +31,7 @@ export interface RedisConfig {
port
:
number
port
:
number
password
:
string
password
:
string
db
:
number
db
:
number
enable_tls
:
boolean
}
}
export
interface
AdminConfig
{
export
interface
AdminConfig
{
...
...
frontend/src/i18n/locales/en.ts
View file @
f2e20670
...
@@ -69,7 +69,9 @@ export default {
...
@@ -69,7 +69,9 @@ export default {
port
:
'
Port
'
,
port
:
'
Port
'
,
password
:
'
Password (optional)
'
,
password
:
'
Password (optional)
'
,
database
:
'
Database
'
,
database
:
'
Database
'
,
passwordPlaceholder
:
'
Password
'
passwordPlaceholder
:
'
Password
'
,
enableTls
:
'
Enable TLS
'
,
enableTlsHint
:
'
Use TLS when connecting to Redis (public CA certs)
'
},
},
admin
:
{
admin
:
{
title
:
'
Admin Account
'
,
title
:
'
Admin Account
'
,
...
...
frontend/src/i18n/locales/zh.ts
View file @
f2e20670
...
@@ -66,7 +66,9 @@ export default {
...
@@ -66,7 +66,9 @@ export default {
port
:
'
端口
'
,
port
:
'
端口
'
,
password
:
'
密码(可选)
'
,
password
:
'
密码(可选)
'
,
database
:
'
数据库
'
,
database
:
'
数据库
'
,
passwordPlaceholder
:
'
密码
'
passwordPlaceholder
:
'
密码
'
,
enableTls
:
'
启用 TLS
'
,
enableTlsHint
:
'
连接 Redis 时使用 TLS(公共 CA 证书)
'
},
},
admin
:
{
admin
:
{
title
:
'
管理员账户
'
,
title
:
'
管理员账户
'
,
...
...
frontend/src/views/setup/SetupWizardView.vue
View file @
f2e20670
...
@@ -91,6 +91,18 @@
...
@@ -91,6 +91,18 @@
</div>
</div>
</div>
</div>
<div
class=
"flex items-center justify-between rounded-xl border border-gray-200 p-3 dark:border-dark-700"
>
<div>
<p
class=
"text-sm font-medium text-gray-900 dark:text-white"
>
{{ t("setup.redis.enableTls") }}
</p>
<p
class=
"text-xs text-gray-500 dark:text-dark-400"
>
{{ t("setup.redis.enableTlsHint") }}
</p>
</div>
<Toggle
v-model=
"formData.redis.enable_tls"
/>
</div>
<div
class=
"grid grid-cols-2 gap-4"
>
<div
class=
"grid grid-cols-2 gap-4"
>
<div>
<div>
<label
class=
"input-label"
>
{{ t('setup.database.username') }}
</label>
<label
class=
"input-label"
>
{{ t('setup.database.username') }}
</label>
...
@@ -517,7 +529,8 @@ const formData = reactive<InstallRequest>({
...
@@ -517,7 +529,8 @@ const formData = reactive<InstallRequest>({
host
:
'
localhost
'
,
host
:
'
localhost
'
,
port
:
6379
,
port
:
6379
,
password
:
''
,
password
:
''
,
db
:
0
db
:
0
,
enable_tls
:
false
},
},
admin
:
{
admin
:
{
email
:
''
,
email
:
''
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment