README.md (12802B)
1 # Introduction 2 3 The sandcastle is a containerized deployment of GNU Taler 4 5 It uses podman to build an image and run a single container that 6 has systemd running inside. 7 8 9 # Prerequisites 10 11 You need (on your host system): 12 13 * podman 14 * bash 15 * Python 3.10 or newer 16 17 The sandcastle-ng container exposes the GNU Taler APIs and Web interfaces 18 through Unix domain sockets. 19 20 Some of these services expect to be accessed via a certain hostname, 21 so it is recommended that you set up the following domain names: 22 23 * `exchange.$MYDOMAIN` for taler-exchange 24 * `backend.$MYDOMAIN` for taler-merchant 25 * `bank.$MYDOMAIN` for libeufin-bank 26 * `landing.$MYDOMAIN` for the demo landing page 27 * `shop.$MYDOMAIN` for the demo blog shop page 28 * `donations.$MYDOMAIN` for the demo donations page 29 * `paivana.$MYDOMAIN` for the demo Paivana paywall 30 31 Your host system should reverse-proxy HTTP(s) traffic to the respective service 32 socket. 33 34 35 # Upgrading Component Versions 36 37 `packages.toml` is the single source of truth for package repositories, tags, 38 Debian paths, dependencies, enabled state, and builders. It uses the same 39 `[repositories]` and `[packages]` layout as 40 `taler-deployment/packaging/ng/packages.toml`. 41 42 Run `./sandcastle-upgrade` to update package tags in `packages.toml` to the 43 latest upstream tag of the respective repository. 44 45 By default only production tags (`vX.Y.Z`, `deb-vX.Y.Z-R`) are considered. 46 Pass `--dev` to also consider dev tags (`vX.Y.Z-dev.N`). 47 Pass `--dry` to only show what would change. 48 Individual components can be given as arguments, e.g. 49 50 ./sandcastle-upgrade --dev taler-exchange gnunet 51 52 Packages whose configured tag is not a supported version tag are left alone. 53 Use `./sandcastle-upgrade --dry` to show available updates without changing the 54 configuration. 55 56 57 # Building the Container Image 58 59 1. Set the package's `tag` in `packages.toml` to the git tag you want to build. 60 61 2. Run `./sandcastle-build` to build the Taler container. The resulting container 62 will be tagged as `taler-base-all`. 63 64 Package builds are incremental. Built Debian packages and their build keys 65 are kept below `packages/`, while downloaded build data is kept below 66 `cache/`. A component is rebuilt when its resolved package configuration, 67 build logic, builder image, or one of its package dependencies changes. 68 Unrelated packages remain untouched. Failed builds are not recorded as 69 current, so they are retried on the next invocation. 70 71 Packages using the `pnpm-workspace` builder are grouped by repository and 72 tag. Each group clones and bootstraps the monorepo once, performs one 73 filtered pnpm install and build for all selected workspace dependency 74 closures, and then creates the individual Debian packages from the prebuilt 75 artifacts. 76 77 Apt, pnpm, Gradle, Cargo, npm, Go, and pip caches are shared between package 78 containers. Source checkouts and package build trees remain fresh. 79 80 Use `./sandcastle-build --no-cache` to rebuild the package builder, every 81 component package, and the final image without cached image layers. Shared 82 dependency and compiler caches are retained. 83 84 By default `sandcastle-build` builds from the `Dockerfile` 85 in the same directory as the script. 86 Anyhow you can pass a different container file like this: 87 88 ./sandcastle-build nightly.Dockerfile 89 90 91 # Configuring the Deployment 92 93 If you just want to play around with the Taler services inside the container, 94 or want to get an integration development environment, 95 there is a nice preset, see below. 96 Thus in these cases no configuration is required 97 and you can skip to "Running the Deployment" below. 98 99 For Taler developers, it is recommended that for each sandcastle deployment, 100 you clone the sandcastle-ng.git repository 101 (https://git.taler.net/sandcastle-ng.git) and create a branch with 102 deployment-specific changes. 103 104 Currently there is not much configuration. 105 106 The main adjustments to be made are: 107 108 * scripts/demo/setup-sandcastle.sh has the currency on top of the file 109 * Services use Unix sockets below `sockets/` by default. Set 110 `SANDCASTLE_SOCKET_DIR` to choose a different host directory. 111 112 To make adjustments for an environment without changing the 113 ``setup-sandcastle.sh`` script, you can use an override file 114 ``overrides/$YOUR_ENVIRONMENT``. This is a bash script that is sourced at the 115 beginning of ``setup-sandcastle.sh`` and can be used to customize 116 environment-specific settings such as hostnames. 117 118 In order to choose an override, 119 set the ``SANDCASTLE_OVERRIDE_NAME`` environment variable 120 before running `./sandcastle-run`: 121 122 SANDCASTLE_OVERRIDE_NAME=$YOUR_ENVIRONMENT ./sandcastle-run 123 124 125 The following variables are typically adjusted in an override file: 126 127 * ``CURRENCY``: Currency of the deployment 128 * ``MYDOMAIN``: Parent domain name for ``{bank,exchange,backend}`` services. 129 * ``EXTERNAL_PORT``: The host port the services will be available on. 130 * ``EXTERNAL_IP``: The host IP the services will be available on. 131 For security reasons this defaults to localhost (127.0.0.1). 132 * ``USE_INSECURE_SANDBOX_PASSWORDS``: 133 If set to `1`, use password `sandbox` for all services instead of random ones. 134 WARNING! Use only when listening to localhost! 135 * ``PAIVANA_DESTINATION``: Upstream website that the Paivana paywall 136 protects. Defaults to `https://www.taler.net/`. Note that this is an 137 *external* server that the container proxies to, it is not served by the 138 sandcastle itself. 139 * ``ENABLE_KYC``: Set to `1` to enable KYC; it is disabled by default. 140 * ``ENABLE_TURNSTILE``: Set to `0` to omit the Drupal Turnstile setup; it is 141 enabled by default. 142 143 144 # Running the Deployment 145 146 Run ``./sandcastle-run`` to run the single container. 147 The container will be named `taler-sandcastle`. 148 Wait until everything has been set up: 149 150 ./sandcastle-wait 151 152 While provisioning is running, this follows the output of 153 ``setup-sandcastle.service`` inside the container. It exits successfully once 154 provisioning has completed, or with a non-zero status if provisioning fails. 155 After a successful deployment, the landing host serves the Sandcastle version, 156 component versions, and deployment time at ``/metrics/sandcastle-status``. 157 158 Note that ``./sandcastle-run`` is just a wrapper around ``podman run``. 159 If required, you can pass addtional arguments to ``./sandcastle-run``. 160 These will be passed on to ``podman run``. Example: 161 162 ./sandcastle-run --log-level=debug 163 164 The running container exposes these services through bind-mounted Unix sockets: 165 166 | Service | Socket | 167 | --- | --- | 168 | Bank | `bank.sock` | 169 | Exchange | `exchange.sock` | 170 | Merchant backend | `merchant-backend.sock` | 171 | Landing page | `landing.sock` | 172 | Blog shop | `blog.sock` | 173 | Donations | `donations.sock` | 174 | Challenger | `challenger.sock` | 175 | Auditor | `auditor.sock` | 176 | Donau | `donau.sock` | 177 | Drupal | `drupal.sock` | 178 | Paivana | `paivana.sock` | 179 180 Exchange, Merchant, the Blog and Donations demos, Auditor, Donau, and Paivana 181 are exposed directly through their native listener or packaged systemd socket 182 activation. Caddy owns the bank socket to bridge libeufin-bank's internal TCP 183 listener, the landing socket to add the Sandcastle status endpoint, the 184 Challenger socket to serve the insecure demo challenges, and the Drupal socket 185 because it is Drupal's HTTP server. 186 187 For example, query the Exchange and merchant configuration endpoints with: 188 189 curl --unix-socket ./sockets/exchange.sock http://localhost/config 190 curl --unix-socket ./sockets/merchant-backend.sock http://localhost/config 191 192 The socket directory defaults to `./sockets`, relative to the repository, and 193 can be changed when starting the deployment: 194 195 SANDCASTLE_SOCKET_DIR=/run/taler-sandcastle ./sandcastle-run 196 197 Missing socket directories are created with mode `1777`, and the sockets have 198 mode `0666`, so a host reverse proxy running as a different user can connect to 199 them. A pre-existing custom directory must allow the relevant container 200 service users to create sockets. The bind mount uses Podman's shared SELinux 201 label; deployments with a confined host reverse proxy may additionally need 202 an appropriate local SELinux policy. 203 204 libeufin-bank does not yet support Unix sockets, so it listens on localhost 205 inside the container and Caddy exposes it through `bank.sock`. 206 207 Overrides that define `EXTERNAL_PORT`, such as `taler.localhost`, continue to 208 publish that single Caddy ingress port for local integration testing. 209 210 When starting sandcastle like 211 212 SANDCASTLE_OVERRIDE_NAME=taler.localhost ./sandcastle-run 213 214 the services will be available as 215 216 - http://taler.localhost:4321 217 - http://bank.taler.localhost:4321 218 - http://shop.taler.localhost:4321 219 - http://donations.taler.localhost:4321 220 - http://backend.taler.localhost:4321 - the merchant backend 221 - http://exchange.taler.localhost:4321 222 - http://auditor.taler.localhost:4321 223 - http://challenger.taler.localhost:4321 224 - http://paivana.taler.localhost:4321/en/ - www.taler.net behind a Taler paywall 225 (use the ``/en/`` entry point, as www.taler.net redirects ``/`` to its own domain) 226 227 This gives a nice environment for integration testing. 228 229 230 # Running the Unit Tests 231 232 Run the Python unit-test suite from the repository root: 233 234 python3 -m unittest discover -s tests -v 235 236 237 # Stopping the deployment 238 239 For stopping the deployment simply run 240 241 ``` 242 ./sandcastle-stop 243 ``` 244 245 which is just a shortcut for ``podman stop taler-sandcastle``. 246 247 248 # Watching Logs 249 250 Run ``./sandcastle-logs`` to watch the logs within the container. 251 You can pass addtional arguments to ``./sandcastle-logs``, 252 which will be passed on to ``journalctl`` in the container. Example: 253 254 ./sandcastle-logs --output=cat 255 256 257 # Poking Around 258 259 You can poke around in a running sandcastle instance by running 260 261 ``` 262 podman exec -it taler-sandcastle /bin/bash 263 ``` 264 265 Or, as a shortcut: 266 267 ``` 268 ./sandcastle-enter 269 ``` 270 271 This will drop you into a shell inside the running container, 272 where you have access to systemd, journalctl, etc. 273 274 275 # Data Storage 276 277 All persistent data is stored in a podman volume called 278 _talerdata_. You can see where it is in your filesystem 279 by running ``podman volume inspect talerdata``. 280 281 That volume also contains the postgres database files. 282 283 ## Cleaning the Data Storage 284 285 For cleaning the data storage run 286 287 ./sandcastle-plow 288 289 and for cleaning also the persistent storage run 290 291 ./sandcastle-plow all 292 293 294 # Provisioning Details 295 296 The whole deployment is configured by a script 297 mounted into the container as ``/provision/setup-sandcastle.sh``. 298 This script will be run as a oneshot systemd service and will disable itself after 299 the first success. 300 301 To troubleshoot, run ``journalctl -u setup-sandcastle.service``. 302 303 There are different setup scripts in the ``scripts/$SANDCASTLE_SETUP_NAME`` 304 folders. Specifically: 305 306 * ``none`` does no setup at all 307 * ``demo`` set up the usual Taler demo 308 * TBD: ``regio`` is a currency conversion setup 309 310 By default, ``demo`` is used. 311 To mount a different provision script, 312 set ``$SANDCASTLE_SETUP_NAME`` when running ``./sandcastle-run``, 313 like this 314 315 SANDCASTLE_SETUP_NAME=none ./sandcastle-run 316 317 318 You can always manually run any of the provisioning script inside the container as 319 ``/scripts/$SANDCASTLE_SETUP_NAME/setup-sandcastle.sh``. 320 321 # Importing / exporting 322 323 To migrate a sandcastle deployment, export / import can be used. 324 325 ``` 326 # Requires taler-sandcastle to be running. 327 # Export the sandcastle data to ./exported/ 328 ./sandcastle-export 329 330 # Other host: 331 # Request an import 332 touch exported/import-request 333 # Now the deployment script will pick up the data to import 334 ./sandcastle-run 335 ``` 336 337 # Neat Things That Already Work 338 339 * Rebulding the base image is incremental, since we use layers. If the tag 340 of the exchange is changed, only the exchange and components that depend 341 on it are rebuilt. 342 * Inside the container, the service names resolve to localhost, 343 and on localhost a reverse proxy with locally signed certificates 344 ensures that services can talk to each other *within* the container 345 by using their *public* base URL. 346 347 348 # Future Extensions 349 350 * Better way to access logs, better way to expose errors during provisioning 351 * The Dockerfile should introduce nightly tags for debian packages it builds. 352 Currently it just uses the latest defined version, which is confusing. 353 * Deploy the Taler woocommerce plugin, wordpress plugin, Joomla plugin 354 * Do self-tests of the deployment using the wallet CLI 355 * Running the auditor 356 * Running a currency conversion setup with multiple libeufin-bank instances 357 * Instead of requiring the reverse proxy to handle TLS, 358 the sandcastle container itself could do TLS termination with caddy. 359 * To improve performance, allow connecting to an external database 360 * Make it easy to import and export the persistent data 361 * Extra tooling to checkpoint images/containers to revert to a previous 362 state quickly.