Creating start9/config.yaml in service

I’m tinkering with building my own StartOS service and would appreciate some help.

I’ve followed the Service Packaging guide and have successfully built, sideloaded, and run the hello-world-startos demo. (Built in an Ubuntu server VM, run in a StartOS VM.) I’ve also learned a lot from consulting many of the other StartOS service wrapper repos on Github (bitcoind-startos, electrs-startos, etc.).

One thing that isn’t clear to me is how to get the start9/config.yaml file in my service’s filesystem. I replicated some of what the electrs-startos project is doing with a configurator that attempts to obtain the bitcoind RPC username and password and put it in a config file for my project. Right now, I’m just trying to replace “Hello World!” with the block height from getblockchaininfo.

I thought I’d see a start9 directory created in my main volume with a config.yaml file according to what is specified in scripts/procedures/getConfig.ts, but I don’t believe my service even has a start9 directory, let alone the config.yaml file that the configurator is looking for.

For now, here is my scripts/procedures/getConfig.ts file:

import { types as T, compat } from "../deps.ts";

export const getConfig: T.ExpectedExports.getConfig = compat.getConfig({
  "dashboard-tor-address": {
    "name": "Dashboard Tor Address",
    "description": "The Tor address for the dashboard.",
    "type": "pointer",
    "subtype": "package",
    "package-id": "btcdash-simple",
    "target": "tor-address",
    "interface": "main",
  },
  username: {
    type: "pointer",
    name: "RPC Username",
    description: "The username for Bitcoin Core's RPC interface",
    subtype: "package",
    "package-id": "bitcoind",
    target: "config",
    multi: false,
    selector: "$.rpc.username",
  },
  password: {
    type: "pointer",
    name: "RPC Password",
    description: "The password for Bitcoin Core's RPC interface",
    subtype: "package",
    "package-id": "bitcoind",
    target: "config",
    multi: false,
    selector: "$.rpc.password",
  },
});

Here is part of my manifest.yaml:

config:
  get:
    type: script
  set:
    type: script
# . . .
dependencies:
  bitcoind:
    version: ">=0.21.1.2 <27.0.0"
    requirement:
      type: required
    description: Used for the RPC connection interface.
    config:
      check:
        type: script
      auto-configure:
        type: script

I appreciate any help with this!

Your manifest.yaml defines where the start9 directory gets created in which config.yaml lives.

See for instance the jam service:

root@jam:/data/start9# ls -al
total 8
drwxr-xr-x 1 root root  42 Dec 18 23:17 .
drwxr-xr-x 1 root root  12 Dec 18 23:17 ..
-rw-r--r-- 1 root root 262 Dec 18 23:17 config.yaml
-rw-r--r-- 1 root root 400 Dec 18 23:17 stats.yaml

Your service’s config and which services your service depends on are what determines which items go into config.yaml

I have the main mount set to /app, which is where my Dockerfile copies the application files needed and where the configurator looks for the config.yaml file (it looks for /app/start9/config.yaml). But in my service logs I see: Error: No such file or directory (os error 2). The service then enters a startup loop.

This is the same error I see when I run the docker image myself on the Ubuntu server VM (where I build the s9pk) and run configurator.

$ docker image load -i docker-images/x86_64.tar
$ docker run --rm -it start9/btcdash-simple/main:0.0.1 sh
/app # configurator
Error: No such file or directory (os error 2)

The above was only a test to confirm that the error message I see in the StartOS service log is coming from the configurator, which doesn’t find a config.yaml file. I wasn’t expecting the config.yaml to exist, since I only loaded and ran the image on the machine where I built the .s9pk file, rather than in StartOS. My assumption is that because of its contents, the config.yaml file can only be created when starting up the service in StartOS.

I know the configurator is working correctly because if I manually create start9/config.yaml, the configurator works as expected:

/app # mkdir start9
/app # echo -e "username: bitcoin\npassword: redacted" > start9/config.yaml
/app # ls src/config/config.py
ls: src/config/config.py: No such file or directory
/app # configurator
/app # ls src/config/config.py
src/config/config.py

I will keep studying how the manifest.yaml and .ts files work. Or maybe it’s not being created for some other reason, like because the bitcoin service is not fully synced yet.

I’m not the most versed in this but as far as I know:

  1. the config.yaml file is created when the setConfig typescript function is called. Initially, you should probably be putting the service in Needs Config state, then the user will be prompted to configure it and upon saving the config, setConfig will create the file.

  2. configurator is an application that you’d have to include in the container – afaik it won’t exist unless you put it in there. There are very few services that still use a configurator - nextcloud and bitcoin are among them but it’s not necessary. See monero for an example with lots of config options and no configurator:
    GitHub - kn0wmad/monerod-wrapper: Wrapper for the Monero Daemon

I don’t know what my exact problem was, but after tinkering more with the .ts files I finally got the start9/config.yaml file to show up in the main volume. My guess is that I didn’t have something set up right with backups or properties or something in manifest.yaml, because config.yaml showed up after switching to using scripts for everything. For example, I switched from using docker-type backups (like bitcoind-startos) to the script-type backups (like electrs-startos and specter-startos) in manifest.yaml.

Also one more note, in case this will help anyone: After I fixed the scripts, I noticed that I only had a start9/config.yaml file in my main volume (/app). It looks like this directory gets overwritten when the service starts, because my Dockerfile was copying many files to that same directory when building the docker images. The fix here was to change my main volume to something else like /data. Now I can access /data/start9/config.yaml, extract the RPC values I need, and save them to a config file in /app/src/config/ for my application.

Thank you for the help, George. I like the simpler approach to creating the config file directly in docker_entrypoint.sh rather than using a configurator.