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
66 changes: 66 additions & 0 deletions doc/docs/server_config/custom-ports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
sidebar_position: 12
description: How to change the ports Watcharr runs on.
---

# Port Configuration

If you're running outside of docker, you may run in to port conflicts with the defaults in Watcharr. You can override these with settings in the `watcharr.json`.

## Watcharr Service Itself

The main part of Watcharr.

Partial Example:

```json
{
"API_PORT": 4090,
"API_HOST": "127.0.0.1",
... // The rest of the json
}
```

### API_PORT

Default: `3080`
Description: Configures the port the Watcharr service listens to.
Location: This value is at the root of the `watcharr.json`.

### API_HOST

Default: `0.0.0.0`
Description: What interface IP to bind to, if running behind a proxy `127.0.0.1` is probably more appropriate.
Location: This value is at the root of the `watcharr.json`.

## The Node.JS Web Asset Server

This is what serves js/html/image files.

### WEB_ASSET_SERVER

This is an object at the root of the `watcharr.json` it contains the following options.

Partial Example:

```json
{
"WEB_ASSET_SERVER": {
"port": 3333,
"host": "10.88.0.1"
}
... // The rest of the json
}
```

#### port

Default: `3000`
Description: The port the web asset server listens on. The main watcharr executable is the only thing that talks to this directly.
Location: Within the `WEB_ASSET_SERVER` object.

#### host

Default: `127.0.0.1`
Description: What interface IP to bind to.
Location: Within the `WEB_ASSET_SERVER` object.
14 changes: 0 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 55 additions & 8 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ var DataPath = func() string {
return path
}()

// WebAssetServerSetting configures the nodejs webserver
type WebAssetServerSetting struct {
Port uint16 `json:"port"`
Host string `json:"host"`
}

type TrustedHeaderAuthSetting struct {
// Required: Should header auth be enabled?
// This bool exists so header auth can be toggled
Expand Down Expand Up @@ -51,6 +57,12 @@ type ServerConfig struct {
// TODO Enforce iso_3166_1 validity (same as tmdb)
DEFAULT_COUNTRY string `json:",omitempty"`

// The port Watcharr's API Runs on
API_PORT uint16 `json:",omitempty"`

// The host the API should bind to
API_HOST string `json:",omitempty"`

// Optional: Point to your Jellyfin install
// to enable it as an auth provider.
JELLYFIN_HOST string `json:",omitempty"`
Expand Down Expand Up @@ -91,6 +103,9 @@ type ServerConfig struct {
// of failure.
// Set to `true` to enable.
DEBUG bool `json:",omitempty"`

// Details for the web asset server run with nodejs
WEB_ASSET_SERVER WebAssetServerSetting `json:",omitempty"`
}

// ServerConfig, but with JWT_SECRET removed from json.
Expand All @@ -101,6 +116,8 @@ type ServerConfig struct {
// not editable on frontend, so not needed).
func (c *ServerConfig) GetSafe() ServerConfig {
return ServerConfig{
API_PORT: c.API_PORT,
API_HOST: c.API_HOST,
SIGNUP_ENABLED: c.SIGNUP_ENABLED,
DEFAULT_COUNTRY: c.DEFAULT_COUNTRY,
JELLYFIN_HOST: c.JELLYFIN_HOST,
Expand Down Expand Up @@ -143,30 +160,39 @@ func (c *ServerConfig) Get(s string) (ServerConfigGetByName, error) {
return ServerConfigGetByName{Value: c.HEADER_AUTH}, nil
case "DEBUG":
return ServerConfigGetByName{Value: c.DEBUG}, nil
case "API_PORT":
return ServerConfigGetByName{Value: c.API_PORT}, nil
case "API_HOST":
return ServerConfigGetByName{Value: c.API_HOST}, nil
}
return ServerConfigGetByName{}, errors.New("invalid setting")
}

// Update server config property
// UpdateConfig updates server config property
func (c *ServerConfig) UpdateConfig(k string, v any) error {
slog.Debug("updateConfig", "k", k, "v", v)
if v == nil {
return errors.New("invalid value")
}
if k == "JELLYFIN_HOST" {
switch k {
case "JELLYFIN_HOST":
c.JELLYFIN_HOST = v.(string)
} else if k == "USE_EMBY" {
case "USE_EMBY":
c.USE_EMBY = v.(bool)
} else if k == "SIGNUP_ENABLED" {
case "SIGNUP_ENABLED":
c.SIGNUP_ENABLED = v.(bool)
} else if k == "TMDB_KEY" {
case "TMDB_KEY":
c.TMDB_KEY = v.(string)
} else if k == "DEBUG" {
case "DEBUG":
c.DEBUG = v.(bool)
logging.SetLevel(c.DEBUG)
} else if k == "DEFAULT_COUNTRY" {
case "DEFAULT_COUNTRY":
c.DEFAULT_COUNTRY = v.(string)
} else {
case "API_PORT":
c.API_PORT = v.(uint16)
case "API_HOST":
c.API_HOST = v.(string)
default:
return errors.New("invalid setting")
}
err := c.Write()
Expand Down Expand Up @@ -250,6 +276,18 @@ func initFromConfig(c *ServerConfig) {
if c.JWT_SECRET == "" {
log.Fatal("JWT_SECRET missing from config!")
}
if c.API_PORT == 0 {
c.API_PORT = 3080
}
if c.API_HOST == "" {
c.API_HOST = "0.0.0.0"
}
if c.WEB_ASSET_SERVER.Port == 0 {
c.WEB_ASSET_SERVER.Port = 3000
}
if c.WEB_ASSET_SERVER.Host == "" {
c.WEB_ASSET_SERVER.Host = "127.0.0.1"
}
}

// Generate new barebones watcharr.json config file.
Expand All @@ -264,6 +302,8 @@ func generateConfig() (*ServerConfig, error) {
// Other defaults..
DEFAULT_COUNTRY: "US",
SIGNUP_ENABLED: true,
API_PORT: 3080,
API_HOST: "0.0.0.0",
}
barej, err := json.MarshalIndent(cfg, "", "\t")
if err != nil {
Expand All @@ -279,5 +319,12 @@ func Get() (*ServerConfig, error) {
if err != nil {
return nil, err
}
// for existing config files
if cfg.API_PORT == 0 {
cfg.API_PORT = 3080
}
if cfg.API_HOST == "" {
cfg.API_HOST = "0.0.0.0"
}
return cfg, nil
}
42 changes: 42 additions & 0 deletions server/config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package config

import (
"encoding/json"
"strings"
"testing"

"github.com/stretchr/testify/require"
)

var envTests = []struct {
name string
json string
expected WebAssetServerSetting
}{
{
"empty",
`{"JWT_SECRET": "sekret"}`,
WebAssetServerSetting{Host: "127.0.0.1", Port: 3000},
},
{
"full",
`{
"JWT_SECRET": "sekret",
"WEB_ASSET_SERVER": { "port": 9090, "host": "0.0.0.0" }
}`,
WebAssetServerSetting{Host: "0.0.0.0", Port: 9090},
},
}

func TestNewWebAssetServer(t *testing.T) {
for _, tt := range envTests {
t.Run(tt.name, func(t *testing.T) {
actual := new(ServerConfig)
dec := json.NewDecoder(strings.NewReader(tt.json))
err := dec.Decode(actual)
require.NoError(t, err)
initFromConfig(actual)
require.Equal(t, tt.expected, actual.WEB_ASSET_SERVER)
})
}
}
6 changes: 4 additions & 2 deletions server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ require (
github.com/gin-contrib/cors v1.7.6
github.com/gin-gonic/gin v1.11.0
github.com/go-co-op/gocron/v2 v2.16.2
github.com/go-playground/validator/v10 v10.27.0
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/jinzhu/copier v0.4.0
github.com/joho/godotenv v1.5.1
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62
github.com/stretchr/testify v1.11.1
golang.org/x/crypto v0.40.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gorm.io/driver/sqlite v1.6.0
Expand All @@ -24,15 +26,14 @@ require (
github.com/bytedance/sonic/loader v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.6 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.27.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/gomodule/redigo v1.9.2 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
Expand All @@ -46,6 +47,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.54.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
Expand Down
Loading