Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve systemd docs and simplify config file arithmetics #3480

Closed
wants to merge 17 commits into from
Closed
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
1 change: 1 addition & 0 deletions .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on =
"OCIS_URL": OCIS_URL,
"PROXY_TLS": "true",
"OCIS_BASE_DATA_PATH": "/mnt/data/ocis",
"OCIS_CONFIG_DIR": "/etc/ocis",
# change default secrets
"OCIS_JWT_SECRET": "Pive-Fumkiu4",
"STORAGE_TRANSFER_SECRET": "replace-me-with-a-transfer-secret",
Expand Down
1 change: 1 addition & 0 deletions .make/release.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ release-dirs:

# docker specific packaging flags
DOCKER_LDFLAGS += -X "$(OCIS_REPO)/ocis-pkg/config/defaults.BaseDataPathType=path" -X "$(OCIS_REPO)/ocis-pkg/config/defaults.BaseDataPathValue=/var/lib/ocis"
DOCKER_LDFLAGS += -X "$(OCIS_REPO)/ocis-pkg/config/defaults.BaseConfigPathType=path" -X "$(OCIS_REPO)/ocis-pkg/config/defaults.BaseConfigPathValue=/etc/ocis"

release-linux-docker-amd64: release-dirs
GOOS=linux \
Expand Down
1 change: 1 addition & 0 deletions docs/helpers/configenvextractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func GenerateIntermediateCode(templatePath string, intermediateCodePath string,
func RunIntermediateCode(intermediateCodePath string) {
fmt.Println("Running intermediate go code for " + intermediateCodePath)
os.Setenv("OCIS_BASE_DATA_PATH", "~/.ocis")
os.Setenv("OCIS_CONFIG_DIR", "~/.ocis/config")
out, err := exec.Command("go", "run", intermediateCodePath).Output()
if err != nil {
log.Fatal(err)
Expand Down
17 changes: 11 additions & 6 deletions docs/ocis/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,20 @@ Let's explore the various flows with examples and workflows.

Let's explore with examples this approach.

#### Expected loading locations:
#### Expected loading locations
wkloucek marked this conversation as resolved.
Show resolved Hide resolved

- `$HOME/.ocis/config/`
- `/etc/ocis/`
- `.config/`
- docker images: `/etc/ocis/`
- binary releases: `$HOME/.ocis/config/`

followed by the extension name. When configuring the proxy, a valid full path that will get loaded is `$HOME/.ocis/config/proxy.yaml`.
followed by the `<extension name>.yaml`, eg `proxy.yaml` for the extension configuration. You also can put an `ocis.yaml` config file to the expected loading location to use a single config file.

#### Only config files
You can set another directory as config path in the environment variable `OCIS_CONFIG_DIR`. It will then pick the same file names, but from the folder you configured.
Copy link
Contributor

@dragonchaser dragonchaser May 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer:

"You can override the config path using the environment variable OCIS_CONFIG_DIR.
The same config filenames will be used, but the configs will be red from the changed config path."


Another option is to set the `--ocis-config-file` option for the runtime `ocis server --ocis-config-file /path/to/ocis.yaml` or for an extension without runtime `ocis proxy --ocis-config-file /path/to/ocis.yaml server`. For both cases, you can achieve the same by setting the environment variable `OCIS_CONFIG_FILE=/path/to/ocis.yaml`.

For unsupervised extensions (without runtime), you also can specify a `--config-file` flag to use a non default config file, eg. `ocis proxy server --config-file /path/to/proxy.yaml`. An alternative is to set the extension specific configuration file path environment variable, e.g. `PROXY_CONFIG_FILE=/path/to/proxy.yaml` for the proxy extension.

#### Only config files

The following config files are present in the default loading locations:

Expand Down
20 changes: 14 additions & 6 deletions docs/ocis/deployment/systemd.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ geekdocFilePath: systemd.md
{{< toc >}}

## Install the oCIS binary

Download the oCIS binary of your preferred version and for your CPU architecture and operating system from [download.owncloud.com](https://download.owncloud.com/ocis/ocis).

Rename the downloaded binary to `ocis` and move it to `/usr/bin/`. As a next step, you need to mark it as executable with `chmod +x /usr/bin/ocis`.
Copy link
Contributor

@dragonchaser dragonchaser May 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/usr/local/bin should be the valid path here. The systems package manager should not interfere with that folder.


When you now run `ocis help` on your command line, you should see the available options for the oCIS command.


## Systemd service definition

Create the Systemd service definition for oCIS in the file `/etc/systemd/system/ocis.service` with following content:
```

```systemd
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExecStart should have a full path to the binary, do not expect that $PATH is set up properly :D

[Unit]
Description=OCIS server

Expand All @@ -36,19 +37,23 @@ Restart=always
WantedBy=multi-user.target
```

For reasons of simplicity we are using the root user and group to run oCIS which is not recommended. Please use a non-root user in production environments and modify the oCIS service definition accordingly.

{{< hint danger >}}
For reasons of simplicity we are using the root user and group to run oCIS, which is not recommended. Please use only privileged users in production environments and modify the oCIS service definition accordingly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should definitely adapt our sample service file instead of this comment in the future.

{{< /hint >}}

In the service definition we referenced `/etc/ocis/ocis.env` as our file containing environment variables for the oCIS process.
In order to create the file we need first to create the folder `/etc/ocis/` and than we can add the actual `/etc/ocis/ocis.env` with following content:

```
OCIS_URL=https://some-hostname-or-ip:9200
```bash
OCIS_URL=https://some-host-or-ip:9200
PROXY_HTTP_ADDR=0.0.0.0:9200
OCIS_INSECURE=false

OCIS_LOG_LEVEL=error

OCIS_BASE_DATA_PATH=/var/lib/ocis
OCIS_CONFIG_DIR=/etc/ocis

GLAUTH_LDAPS_CERT=/etc/ocis/ldap/ldaps.crt
GLAUTH_LDAPS_KEY=/etc/ocis/ldap/ldaps.key
IDP_TRANSPORT_TLS_CERT=/etc/ocis/idp/server.crt
Expand All @@ -59,6 +64,9 @@ PROXY_TRANSPORT_TLS_KEY=/etc/ocis/proxy/server.key

Please change your `OCIS_URL` in order to reflect your actual deployment. If you are using self signed certificates you need to set `OCIS_INSECURE=true` in `/etc/ocis/ocis.env`.

In the `ocis.env` file we configured oCIS to store all data in `/var/lib/ocis`, so you need to create that folder and make it writeable for the ocis user (see user / group in the systemd file).

If you add oCIS config files in `/etc/ocis`, you need to ensure that the directory and config file is readable by the oCIS process's user / group.

## Starting the oCIS service

Expand Down
12 changes: 12 additions & 0 deletions extensions/accounts/pkg/command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ func Server(cfg *config.Config) *cli.Command {
Name: "server",
Usage: fmt.Sprintf("start %s extension without runtime (unsupervised mode)", cfg.Service.Name),
Category: "server",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config-file",
Value: cfg.ConfigFile,
Usage: "config file to be loaded by the extension",
Destination: &cfg.ConfigFile,
},
&cli.StringFlag{
Name: "ocis-config-file",
Hidden: true,
},
},
Before: func(c *cli.Context) error {
return parser.ParseConfig(cfg)
},
Expand Down
2 changes: 2 additions & 0 deletions extensions/accounts/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ type Config struct {
HashDifficulty int `yaml:"hash_difficulty" env:"ACCOUNTS_HASH_DIFFICULTY" desc:"The hash difficulty makes sure that validating a password takes at least a certain amount of time."`
DemoUsersAndGroups bool `yaml:"demo_users_and_groups" env:"ACCOUNTS_DEMO_USERS_AND_GROUPS" desc:"If this flag is set the service will setup the demo users and groups."`

ConfigFile string `yaml:"-" env:"ACCOUNTS_CONFIG_FILE" desc:"config file to be used by the accounts extension"`

Context context.Context `yaml:"-"`
}

Expand Down
2 changes: 2 additions & 0 deletions extensions/accounts/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ func FullDefaultConfig() *config.Config {

func DefaultConfig() *config.Config {
return &config.Config{
ConfigFile: path.Join(defaults.BaseConfigPath(), "accounts.yaml"),

Debug: config.Debug{
Addr: "127.0.0.1:9182",
Token: "",
Expand Down
24 changes: 20 additions & 4 deletions extensions/accounts/pkg/config/parser/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,45 @@ import (

"github.com/owncloud/ocis/extensions/accounts/pkg/config"
defaults "github.com/owncloud/ocis/extensions/accounts/pkg/config/defaults"
"github.com/owncloud/ocis/extensions/accounts/pkg/logging"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"

"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
)

// ParseConfig loads accounts configuration from known paths.
func ParseConfig(cfg *config.Config) error {
_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg)

// cfg.ConfigFile can be set via env variable, therefore we need to do a environment variable run first
if err := loadEnv(cfg); err != nil {
return err
}

_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg.ConfigFile, cfg.ConfigFile != defaults.DefaultConfig().ConfigFile, cfg)
if err != nil {
logger := logging.Configure(cfg.Service.Name, &config.Log{})
logger.Error().Err(err).Msg("couldn't find the specified config file")
return err
}

defaults.EnsureDefaults(cfg)

if err := loadEnv(cfg); err != nil {
return err
}

defaults.Sanitize(cfg)

return nil
}

func loadEnv(cfg *config.Config) error {
// load all env variables relevant to the config in the current context.
if err := envdecode.Decode(cfg); err != nil {
// no environment variable set for this config is an expected "error"
if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) {
return err
}
}

defaults.Sanitize(cfg)

return nil
}
2 changes: 1 addition & 1 deletion extensions/accounts/pkg/service/v0/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ import (
fieldmask_utils "github.com/mennanov/fieldmask-utils"
"github.com/owncloud/ocis/extensions/accounts/pkg/storage"
accTracing "github.com/owncloud/ocis/extensions/accounts/pkg/tracing"
settings_svc "github.com/owncloud/ocis/extensions/settings/pkg/service/v0"
"github.com/owncloud/ocis/ocis-pkg/log"
"github.com/owncloud/ocis/ocis-pkg/middleware"
"github.com/owncloud/ocis/ocis-pkg/roles"
"github.com/owncloud/ocis/ocis-pkg/sync"
settingssvc "github.com/owncloud/ocis/protogen/gen/ocis/services/settings/v0"
settings_svc "github.com/owncloud/ocis/extensions/settings/pkg/service/v0"
"github.com/rs/zerolog"
merrors "go-micro.dev/v4/errors"
"go-micro.dev/v4/metadata"
Expand Down
12 changes: 12 additions & 0 deletions extensions/audit/pkg/command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ func Server(cfg *config.Config) *cli.Command {
Name: "server",
Usage: fmt.Sprintf("start %s extension without runtime (unsupervised mode)", cfg.Service.Name),
Category: "server",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config-file",
Value: cfg.ConfigFile,
Usage: "config file to be loaded by the extension",
Destination: &cfg.ConfigFile,
},
&cli.StringFlag{
Name: "ocis-config-file",
Hidden: true,
},
},
Before: func(c *cli.Context) error {
return parser.ParseConfig(cfg)
},
Expand Down
2 changes: 2 additions & 0 deletions extensions/audit/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type Config struct {
Events Events `yaml:"events"`
Auditlog Auditlog `yaml:"auditlog"`

ConfigFile string `yaml:"-" env:"AUDIT_CONFIG_FILE" desc:"config file to be used by the audit extension"`

Context context.Context `yaml:"-"`
}

Expand Down
5 changes: 5 additions & 0 deletions extensions/audit/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package defaults

import (
"path"

"github.com/owncloud/ocis/extensions/audit/pkg/config"
"github.com/owncloud/ocis/ocis-pkg/config/defaults"
)

func FullDefaultConfig() *config.Config {
Expand All @@ -15,6 +18,8 @@ func FullDefaultConfig() *config.Config {

func DefaultConfig() *config.Config {
return &config.Config{
ConfigFile: path.Join(defaults.BaseConfigPath(), "audit.yaml"),

Service: config.Service{
Name: "audit",
},
Expand Down
24 changes: 20 additions & 4 deletions extensions/audit/pkg/config/parser/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,45 @@ import (

"github.com/owncloud/ocis/extensions/audit/pkg/config"
"github.com/owncloud/ocis/extensions/audit/pkg/config/defaults"
"github.com/owncloud/ocis/extensions/audit/pkg/logging"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"

"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
)

// ParseConfig loads accounts configuration from known paths.
func ParseConfig(cfg *config.Config) error {
_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg)

// cfg.ConfigFile can be set via env variable, therefore we need to do a environment variable run first
if err := loadEnv(cfg); err != nil {
return err
}

_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg.ConfigFile, cfg.ConfigFile != defaults.DefaultConfig().ConfigFile, cfg)
if err != nil {
logger := logging.Configure(cfg.Service.Name, &config.Log{})
logger.Error().Err(err).Msg("couldn't find the specified config file")
return err
}

defaults.EnsureDefaults(cfg)

if err := loadEnv(cfg); err != nil {
return err
}

defaults.Sanitize(cfg)

return nil
}

func loadEnv(cfg *config.Config) error {
// load all env variables relevant to the config in the current context.
if err := envdecode.Decode(cfg); err != nil {
// no environment variable set for this config is an expected "error"
if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) {
return err
}
}

defaults.Sanitize(cfg)

return nil
}
12 changes: 12 additions & 0 deletions extensions/glauth/pkg/command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ func Server(cfg *config.Config) *cli.Command {
Name: "server",
Usage: fmt.Sprintf("start %s extension without runtime (unsupervised mode)", cfg.Service.Name),
Category: "server",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "config-file",
Value: cfg.ConfigFile,
Usage: "config file to be loaded by the extension",
Destination: &cfg.ConfigFile,
},
&cli.StringFlag{
Name: "ocis-config-file",
Hidden: true,
},
},
Before: func(c *cli.Context) error {
return parser.ParseConfig(cfg)
},
Expand Down
2 changes: 2 additions & 0 deletions extensions/glauth/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type Config struct {

RoleBundleUUID string `yaml:"role_bundle_uuid" env:"GLAUTH_ROLE_BUNDLE_ID"`

ConfigFile string `yaml:"-" env:"GLAUTH_CONFIG_FILE" desc:"config file to be used by the glauth extension"`

Context context.Context `yaml:"-"`
}

Expand Down
2 changes: 2 additions & 0 deletions extensions/glauth/pkg/config/defaults/defaultconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ func FullDefaultConfig() *config.Config {

func DefaultConfig() *config.Config {
return &config.Config{
ConfigFile: path.Join(defaults.BaseConfigPath(), "glauth.yaml"),

Debug: config.Debug{
Addr: "127.0.0.1:9129",
},
Expand Down
25 changes: 21 additions & 4 deletions extensions/glauth/pkg/config/parser/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,45 @@ import (

"github.com/owncloud/ocis/extensions/glauth/pkg/config"
"github.com/owncloud/ocis/extensions/glauth/pkg/config/defaults"
"github.com/owncloud/ocis/extensions/glauth/pkg/logging"
ociscfg "github.com/owncloud/ocis/ocis-pkg/config"

"github.com/owncloud/ocis/ocis-pkg/config/envdecode"
)

// ParseConfig loads accounts configuration from known paths.
func ParseConfig(cfg *config.Config) error {
_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg)

// cfg.ConfigFile can be set via env variable, therefore we need to do a environment variable run first
if err := loadEnv(cfg); err != nil {
return err
}

_, err := ociscfg.BindSourcesToStructs(cfg.Service.Name, cfg.ConfigFile, cfg.ConfigFile != defaults.DefaultConfig().ConfigFile, cfg)
if err != nil {
logger := logging.Configure(cfg.Service.Name, &config.Log{})
logger.Error().Err(err).Msg("couldn't find the specified config file")
return err
}

defaults.EnsureDefaults(cfg)

if err := loadEnv(cfg); err != nil {
return err
}

defaults.Sanitize(cfg)

return nil
}

func loadEnv(cfg *config.Config) error {
// load all env variables relevant to the config in the current context.
if err := envdecode.Decode(cfg); err != nil {
// no environment variable set for this config is an expected "error"
if !errors.Is(err, envdecode.ErrNoTargetFieldsAreSet) {
return err
}
}

// sanitize config
defaults.Sanitize(cfg)
return nil
}
Loading