mirror of
https://codeberg.org/icewind/haze.git
synced 2026-10-01 16:54:08 +02:00
Merge pull request 'Port documentation from Readme.md to mdbook' (#58) from book into main
Reviewed-on: https://codeberg.org/icewind/haze/pulls/58
This commit is contained in:
commit
08df5a11c0
21 changed files with 1073 additions and 519 deletions
58
.forgejo/workflows/book-pr.yaml
Normal file
58
.forgejo/workflows/book-pr.yaml
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
name: "Book - PR"
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- reopened
|
||||||
|
- synchronize
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: page-preview
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
createPreview:
|
||||||
|
runs-on: nix
|
||||||
|
env:
|
||||||
|
SITE_ORIGIN:
|
||||||
|
"https://${{ forge.event.repository.owner.username
|
||||||
|
}}.preview.codeberg.page"
|
||||||
|
SITE_BASEPATH:
|
||||||
|
"/${{ forge.event.repository.name }}@${{ forge.event.number }}/"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: https://codeberg.org/icewind/attic-action@v1
|
||||||
|
with:
|
||||||
|
name: link
|
||||||
|
instance: https://cache.icewind.link
|
||||||
|
authToken: "${{ secrets.ATTIC_TOKEN }}"
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
# git-pages/action doesn't like symlinks
|
||||||
|
cp -r $(nix build .#haze-book --print-out-paths --no-link) dist
|
||||||
|
- name: "Deploy Site"
|
||||||
|
uses: https://code.forgejo.org/actions/git-pages@v2
|
||||||
|
with:
|
||||||
|
site: "${{ env.SITE_ORIGIN }}${{ env.SITE_BASEPATH }}" #
|
||||||
|
token: "${{ forge.token }}" #
|
||||||
|
source: "dist/" #
|
||||||
|
- name: "Find comment"
|
||||||
|
uses: "https://github.com/peter-evans/find-comment@v4" #
|
||||||
|
id: comment
|
||||||
|
with:
|
||||||
|
issue-number: ${{ forge.event.number }} #
|
||||||
|
body-includes: "<!-- preview-comment -->" #
|
||||||
|
- name: "Create or update comment"
|
||||||
|
uses: "https://github.com/peter-evans/create-or-update-comment@v5" #
|
||||||
|
with:
|
||||||
|
issue-number: ${{ forge.event.number }} #
|
||||||
|
comment-id: "${{ steps.comment.outputs.comment-id }}" #
|
||||||
|
edit-mode: "replace"
|
||||||
|
body: |-
|
||||||
|
# Pull request preview ready!
|
||||||
|
|
||||||
|
The Preview of commit ${{ forge.event.pull_request.head.sha }} has been created.
|
||||||
|
You can find it here: ${{ env.SITE_ORIGIN }}${{ env.SITE_BASEPATH }}
|
||||||
|
|
||||||
|
<!-- preview-comment -->
|
||||||
29
.forgejo/workflows/book.yaml
Normal file
29
.forgejo/workflows/book.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
name: "Book"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
preview:
|
||||||
|
runs-on: nix
|
||||||
|
env:
|
||||||
|
SITE_ORIGIN: "${{forge.event.repository.owner.username}}.codeberg.page"
|
||||||
|
SITE_BASEPATH: "/${{forge.event.repository.name}}/"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: https://codeberg.org/icewind/attic-action@v1
|
||||||
|
with:
|
||||||
|
name: link
|
||||||
|
instance: https://cache.icewind.link
|
||||||
|
authToken: "${{ secrets.ATTIC_TOKEN }}"
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
# git-pages/action doesn't like symlinks
|
||||||
|
cp -r $(nix build .#haze-book --print-out-paths --no-link) dist
|
||||||
|
- uses: https://codeberg.org/git-pages/action@v2
|
||||||
|
with:
|
||||||
|
site: https://${{ env.SITE_ORIGIN }}${{ env.SITE_BASEPATH }}
|
||||||
|
token: ${{ forge.token }}
|
||||||
|
source: dist/
|
||||||
530
README.md
530
README.md
|
|
@ -9,537 +9,29 @@ Easy setup and management of Nextcloud test instances using docker
|
||||||
`haze` provides an easy way to set up Nextcloud test instances with a choice of
|
`haze` provides an easy way to set up Nextcloud test instances with a choice of
|
||||||
php version, database server, optional s3 or ldap setup and more.
|
php version, database server, optional s3 or ldap setup and more.
|
||||||
|
|
||||||
## Setup
|
## Documentation
|
||||||
|
|
||||||
### Requirements
|
Documentation for haze can be found in the
|
||||||
|
[book](https://icewind.codeberg.page/haze/)
|
||||||
|
|
||||||
- Docker
|
## Quickstart
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
- Grab a binary from the
|
- Grab a binary from the
|
||||||
[Codeberg releases](https://codeberg.org/icewind/haze/releases) and place it
|
[Codeberg releases](https://codeberg.org/icewind/haze/releases) and place it
|
||||||
in your `$PATH`
|
in your `$PATH`
|
||||||
|
|
||||||
### Config
|
- Create a file `~/.config/haze/haze.toml` with the following content:
|
||||||
|
|
||||||
Create a file `~/.config/haze/haze.toml` with the following options:
|
```toml
|
||||||
|
sources_root = "/path/to/nextcloud/sources"
|
||||||
```toml
|
|
||||||
sources_root = "/path/to/nextcloud/sources"
|
|
||||||
```
|
|
||||||
|
|
||||||
See the [configuration section](#configuration) for more options.
|
|
||||||
|
|
||||||
### Quick examples
|
|
||||||
|
|
||||||
- Start a Nextcloud instance with `postgresql`, and `s3` primary storage:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze start pgsql s3
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- Start a Nextcloud instance with `sqlite`, `php 8.3` and an `smb` external
|
- Start a basic Nextcloud instance:
|
||||||
storage:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
haze start 8.3 smb
|
haze start
|
||||||
```
|
```
|
||||||
|
|
||||||
- Run specific units test against an `oracle` database
|
- Navigate to the address that is provided in the output.
|
||||||
```bash
|
|
||||||
haze test oracle apps/dav/tests/unit/Connector/Sabre
|
|
||||||
```
|
|
||||||
|
|
||||||
## Managing instances
|
See the [book](https://icewind.codeberg.page/haze/) for more details.
|
||||||
|
|
||||||
#### Start an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze start [--name <name>] [--detach] [database] [php-version] [services] [vX.Y.Z]
|
|
||||||
```
|
|
||||||
|
|
||||||
Where `database` is one of `sqlite`, `mysql`, `mariadb`, `pgsql` or `oracle`
|
|
||||||
with an optional version (e.g. `pgsql:12`), defaults to `sqlite`. And
|
|
||||||
`php-version` is one of `8.0`, `8.1`, `8.2`, `8.3`, `8.4` or `8.5`, defaults to
|
|
||||||
the maximum version support by the current Nextcloud version.
|
|
||||||
|
|
||||||
You can specify a version number (e.g. `v32.0.2`) to use the sources from a
|
|
||||||
release instead of using the local sources.
|
|
||||||
|
|
||||||
Use `--name <name>` to give the instance a specific name instead of a randomly
|
|
||||||
generated one. For example:
|
|
||||||
|
|
||||||
Use `--detach` to give the instance
|
|
||||||
[its own sources](#instances-with-their-own-sources) instead of sharing
|
|
||||||
`sources_root` with all other instances.
|
|
||||||
|
|
||||||
Additionally, you can use the following options when starting an instance:
|
|
||||||
|
|
||||||
- `s3`: set up an S3 server and configure to Nextcloud to use it as primary
|
|
||||||
storage.
|
|
||||||
- `s3s`: enable TLS for the S3 setup.
|
|
||||||
- `s3mb`: enable multi-bucket S3 setup.
|
|
||||||
- `s3m`: enable multi-instance S3 setup.
|
|
||||||
- `ldap`: set up an LDAP server.
|
|
||||||
- `saml`: set up authentik as a SAML IDP.
|
|
||||||
- `oidc`: set up authentik as an OIDC IDP.
|
|
||||||
- `scim`: set up authentik as a SCIM server.
|
|
||||||
- `office`: set up a Nextcloud Office server.
|
|
||||||
- `onlyoffice` setup an onlyoffice document server.
|
|
||||||
- `push` set up [client push](https://github.com/nextcloud/notify_push).
|
|
||||||
- `smb`: set up a samba server for external storage use.
|
|
||||||
- `dav`: set up a WebDAV server for external storage use.
|
|
||||||
- `sftp`: set up a SFTP server for external storage use.
|
|
||||||
- `sftp-key`: set up a SFTP server for external storage use with public key
|
|
||||||
authentication.
|
|
||||||
- `kaspersky`: set up a kaspersky scan engine server in http mode. ( Requires
|
|
||||||
[manually setting up the image](https://github.com/icewind1991/kaspersky-docker))
|
|
||||||
- `kaspersky-icap`: setup a kaspersky scan engine server in ICAP mode.
|
|
||||||
- `clamav`: set up a local clam av scanner in executable mode.
|
|
||||||
- `clamav-socket`: set up a clam av scanner in socket mode.
|
|
||||||
- `clamav-icap`: set up a clam av scanner in ICAP mode.
|
|
||||||
- `clamav-icap-tls`: set up a clam av scanner in ICAP mode with TLS encryption.
|
|
||||||
- `oc`: start an ownCloud instance in the same network.
|
|
||||||
- `imaginary`: start an Imaginary service and configure it for preview
|
|
||||||
generation.
|
|
||||||
- `mail`: start a [smtp4dev](https://github.com/rnwood/smtp4dev) server and
|
|
||||||
configure it the mail server.
|
|
||||||
- `webhook` start a
|
|
||||||
[webhook tester](https://github.com/tarampampam/webhook-tester)
|
|
||||||
- `redis`: start a separate container for redis.
|
|
||||||
- `redis-tls`: connect to redis over TLS.
|
|
||||||
- `<path to app.tar.gz>`: by specifying the path to an app package this package
|
|
||||||
will be extracted into the apps. directory of the new instance (overwriting
|
|
||||||
any existing app code). This can be used to quickly test a packaged app.
|
|
||||||
- The name of any configured preset.
|
|
||||||
|
|
||||||
#### Run tests in a new instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze test [database] [php-version] [phpunit version] [path]
|
|
||||||
```
|
|
||||||
|
|
||||||
Where `path` is a file or folder to run PHPUnit in, relative to the sources
|
|
||||||
root.
|
|
||||||
|
|
||||||
### List running instances
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze list
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Remove all running instances
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze clean
|
|
||||||
```
|
|
||||||
|
|
||||||
### Instances with their own sources
|
|
||||||
|
|
||||||
By default every instance shares the sources configured as `sources_root`, so
|
|
||||||
all instances always run the same code. An instance started with `--detach` gets
|
|
||||||
its own `git worktree` of `sources_root` instead, created in `worktree_dir`,
|
|
||||||
which lets you run several instances on different branches at the same time.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze start --name my-fix --detach
|
|
||||||
```
|
|
||||||
|
|
||||||
The worktree is checked out with a detached head. Every app in one of the
|
|
||||||
`app_directories` that gets enabled during setup receives its own worktree as
|
|
||||||
well, other apps keep running from the shared app directory.
|
|
||||||
|
|
||||||
The worktrees are removed together with the instance, by `haze stop` or
|
|
||||||
`haze clean`.
|
|
||||||
|
|
||||||
## Controlling running instances
|
|
||||||
|
|
||||||
The following commands run against the most recently started instance and allow
|
|
||||||
optionally providing a `match` to select a specific instance by its name.
|
|
||||||
|
|
||||||
#### Open an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] open
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Open the database of an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] db
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Execute a command on an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] [service] [cmd]
|
|
||||||
```
|
|
||||||
|
|
||||||
If no `cmd` is specified it will launch `bash`
|
|
||||||
|
|
||||||
If a service name or `db` is provided, the command will be in the container of
|
|
||||||
the service or database.
|
|
||||||
|
|
||||||
#### Create a new instance and run a command
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] shell [cmd]
|
|
||||||
```
|
|
||||||
|
|
||||||
If no `cmd` is specified it will launch `bash`
|
|
||||||
|
|
||||||
#### Execute an occ command on an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] occ [cmd]
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Connect to the database on an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] db
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Show the logs of an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] logs
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Stop an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] stop
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Pin an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] pin
|
|
||||||
```
|
|
||||||
|
|
||||||
Pinned instances will not be removed by `haze clean`.
|
|
||||||
|
|
||||||
#### Unpin an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] unpin
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Run a command with instance environment variables set
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] env <cmd> [args]
|
|
||||||
```
|
|
||||||
|
|
||||||
Runs the provided command with `NEXTCLOUD_URL`, `DATABASE_URL` and `REDIS_URL`
|
|
||||||
environment variables set for the matched instance.
|
|
||||||
|
|
||||||
This is intended to run a local
|
|
||||||
[push daemon](https://github.com/nextcloud/notify_push) against an instance.
|
|
||||||
|
|
||||||
#### Update the container images
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze update
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Edit a file in an instance with the local $EDITOR
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] edit <path>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Reload the php config of an instance
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze [match] reload
|
|
||||||
```
|
|
||||||
|
|
||||||
The php configuration can edit changed with `haze edit /config/php.ini`
|
|
||||||
|
|
||||||
#### Checkout a branch for all local apps
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze git checkout [branch]
|
|
||||||
```
|
|
||||||
|
|
||||||
Checks out the branch in all git repositories within the apps folder.
|
|
||||||
|
|
||||||
Defaults to the branch matching the current checked out server versions (e.g.
|
|
||||||
`master` or `stable33`).
|
|
||||||
|
|
||||||
`master` and `main` can be used interchangeably.
|
|
||||||
|
|
||||||
#### Pull remote changes for all local apps
|
|
||||||
|
|
||||||
```bash
|
|
||||||
haze git pull
|
|
||||||
```
|
|
||||||
|
|
||||||
Performs a pull in all git repositories within the apps folder.
|
|
||||||
|
|
||||||
## Federation
|
|
||||||
|
|
||||||
Multiple instances can reach each other by using their instance name as domain
|
|
||||||
name to allow for testing federation between instances. Alternatively, you can
|
|
||||||
set up the haze proxy and the proxied domains to get https support between
|
|
||||||
instances.
|
|
||||||
|
|
||||||
## Proxy
|
|
||||||
|
|
||||||
By default, instances can be accessed by their IP. In order to get more
|
|
||||||
memorable URLs and allow supporting https, haze comes with a builtin reverse
|
|
||||||
proxy to allow using a wildcard domain.
|
|
||||||
|
|
||||||
### DNS Setup
|
|
||||||
|
|
||||||
#### Requirements
|
|
||||||
|
|
||||||
- A domain name you can set wildcard DNS records for
|
|
||||||
- A reverse proxy like Nginx or Apache
|
|
||||||
- (optionally) a wildcard ssl certificate (can be acquiring using letsencrypt
|
|
||||||
and dns verification)
|
|
||||||
|
|
||||||
#### Steps
|
|
||||||
|
|
||||||
- Set a DNS record for `*.haze.example.com` and `haze.example.com` pointing to
|
|
||||||
your development machine.
|
|
||||||
- Set the `proxy` configuration with your domain and desired listen endpoint.
|
|
||||||
- Set up a service to run `haze proxy` in the background as your own user. A
|
|
||||||
systemd user service is recommended (see [haze.service](./haze.service) for an
|
|
||||||
example).
|
|
||||||
- Configure your reverse proxy of choice to proxy `*.haze.example.com` and
|
|
||||||
`haze.example.com` to the proxy's listen endpoint
|
|
||||||
- (optional) acquire a wildcard ssl certificate for your domain and set your
|
|
||||||
reverse proxy to use it. This will be highly dependent on your DNS provider,
|
|
||||||
[this](https://community.letsencrypt.org/t/dns-providers-who-easily-integrate-with-lets-encrypt-dns-validation/86438)
|
|
||||||
lists some DNS providers and supported ACME clients.
|
|
||||||
|
|
||||||
### Local Setup
|
|
||||||
|
|
||||||
- Setup `dnsmasq` to resolve `*.haze.test` to your development machine.
|
|
||||||
- Generate a wildcard ssl certificate for `*.haze.test` using `mkcert`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Generate local wildcard certificate
|
|
||||||
mkcert -cert-file <path-to-your-certificats>haze.test.crt -key-file <path-to-your-certificats>haze.test.key '*.haze.test'
|
|
||||||
```
|
|
||||||
|
|
||||||
- Set up a service to run `haze proxy` in the background as your own user. A
|
|
||||||
systemd user service is recommended (see [haze.service](./haze.service) for an
|
|
||||||
example).
|
|
||||||
- Either point haze at the certificate directly:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[proxy]
|
|
||||||
address = "haze.test"
|
|
||||||
https = true
|
|
||||||
listen = "127.0.0.1:443"
|
|
||||||
cert = "<path-to-your-certificats>/haze.test.crt"
|
|
||||||
key = "<path-to-your-certificats>/haze.test.key"
|
|
||||||
```
|
|
||||||
|
|
||||||
Binding to port 443 as a regular user requires either
|
|
||||||
`sudo setcap cap_net_bind_service=+ep $(which haze)` or
|
|
||||||
`sysctl net.ipv4.ip_unprivileged_port_start=443`.
|
|
||||||
|
|
||||||
- Or, if you already have another web server, setup it up to proxy `*.haze.test`
|
|
||||||
and `haze.test` to the `haze proxy`'s socket. Example for Nginx:
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
upstream haze-handler {
|
|
||||||
server unix:/run/haze/haze.sock;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen 443 ssl;
|
|
||||||
http2 on;
|
|
||||||
server_name *.haze.test;
|
|
||||||
|
|
||||||
ssl_certificate <path-to-your-certificats>/haze.test.crt;
|
|
||||||
ssl_certificate_key <path-to-your-certificats>/haze.test.key;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://haze-handler;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
When the proxy is configured, generated URLs for the instances will use a
|
|
||||||
subdomain of the configured domain, e.g. the `rolling-bees` instance will be
|
|
||||||
available at `rolling-bees.haze.example.com`. Additionally, `haze.example.com`
|
|
||||||
will automatically point to the last created instance.
|
|
||||||
|
|
||||||
Additionally, the proxy allows access to the server containers trough either
|
|
||||||
`<instance id>-<service id>.haze.example.com` for a specific instance, or
|
|
||||||
`<service-id>.haze.example.com` for the last created instance. For example
|
|
||||||
`rolling-bees-mail.haze.example.com` will give access to the smtp4dev web
|
|
||||||
interface of the `rolling-bees` instance.
|
|
||||||
|
|
||||||
## Haze scripts
|
|
||||||
|
|
||||||
Haze scripts combine a set of instance options and a script to run in the
|
|
||||||
instance.
|
|
||||||
|
|
||||||
Haze scripts are intended to way to create automated ways of running more
|
|
||||||
complex tests are setting up more complex instances.
|
|
||||||
|
|
||||||
A script contains of 3 paths
|
|
||||||
|
|
||||||
1. An optional shebang line setting `haze` as the interpreter, e.g.
|
|
||||||
`#! /usr/bin/env -S haze script`
|
|
||||||
2. A shebang line setting the options for the instance creation as the
|
|
||||||
interpreter, e.g. `#! haze shell pgsql s3`
|
|
||||||
3. The rest that is ran as a script inside the created instance.
|
|
||||||
|
|
||||||
The first sheband is set, the script can be ran directly. Else it needs to be
|
|
||||||
run with `haze script [path-to-script]`.
|
|
||||||
|
|
||||||
For example, the following script will create an instance with `postgresql` and
|
|
||||||
`s3` primary storage. Then creates a new file, gets the file id, read the object
|
|
||||||
of the file from S3, validate that it contains the expected contents, and
|
|
||||||
cleanup the instance.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#! #! /usr/bin/env -S haze script
|
|
||||||
#! haze shell pgsql s3
|
|
||||||
|
|
||||||
echo 'test' | occ file:put '-' /admin/files/test.txt
|
|
||||||
FILE_ID=$(occ info:file /admin/files/test.txt | grep fileid: | grep -oE '[0-9]+')
|
|
||||||
OBJECT_CONTENTS=$(occ file:object:get urn:oid:$FILE_ID -)
|
|
||||||
if [ "$OBJECT_CONTENTS" == 'test' ]; then
|
|
||||||
echo "object contains expected contents"
|
|
||||||
else
|
|
||||||
echo "object does not contains expected contents!"
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### Script modes
|
|
||||||
|
|
||||||
Scripts can be either `shell` or `start` scripts.
|
|
||||||
|
|
||||||
`shell` scripts will automatically remove the created instance once the script
|
|
||||||
is done, just like `haze shell` will. The intended use case for this is
|
|
||||||
performing some tests in the created instance without leaving state behind.
|
|
||||||
|
|
||||||
`start` scripts on the other hand will keep the instance, like `haze start`
|
|
||||||
will. The intended use case for this is creating more complex instances without
|
|
||||||
having to configure a dedicated preset.
|
|
||||||
|
|
||||||
The script mode is determined based on the shebang line. The mode set in a
|
|
||||||
script can be overriden by running the script with
|
|
||||||
`haze script [shell|start] path-to-script.sh`.
|
|
||||||
|
|
||||||
## Nushell scripts
|
|
||||||
|
|
||||||
By default, the script contents are executed as either `bash` script, or `nu` script based on the extension.
|
|
||||||
|
|
||||||
You can overwrite the interpreter used to execute the script by adding an extra `#!` line to the script, for example:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#! /usr/bin/env -S haze script
|
|
||||||
#! haze shell pgsql s3
|
|
||||||
#! php -f
|
|
||||||
<?php
|
|
||||||
print("Hello");
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the interpreter used needs to already be available inside the haze container.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
Configuration is loaded from `~/.config/haze/haze.toml` and has the following
|
|
||||||
options
|
|
||||||
|
|
||||||
```toml
|
|
||||||
sources_root = "/path/to/sources" # path of the nextcloud sources. required
|
|
||||||
app_directories = ["/path/to/sources/more_app"] # paths to additional app directories.
|
|
||||||
work_dir = "/path/to/temp/dir" # path to temporary directory. optional, defaults to "/tmp/haze"
|
|
||||||
worktree_dir = "/path/to/worktrees" # where to create the worktrees of detached instances. optional, defaults to "<work_dir>/worktrees"
|
|
||||||
|
|
||||||
[auto_setup] # optional
|
|
||||||
enabled = false # whether or not to automatically install nextcloud on `haze start`. enabled by default
|
|
||||||
username = "foo" # username for admin user during auto setup. optional, defaults to "admin"
|
|
||||||
password = "bar" # password for admin user during auto setup. optional, defaults to "admin"
|
|
||||||
enable_apps = ["files_external"] # apps to enable after setup, defaults to []
|
|
||||||
disable_apps = ["contacts"] # apps to disable after setup, defaults to []
|
|
||||||
post_setup = [# commands to execute after setup, defaults to []
|
|
||||||
"occ group:add test",
|
|
||||||
]
|
|
||||||
config = { "foo" = "bar" } # configuration options to set before install
|
|
||||||
|
|
||||||
[[volume]] # optional
|
|
||||||
source = "/tmp/haze-shared"
|
|
||||||
target = "/shared"
|
|
||||||
create = true
|
|
||||||
|
|
||||||
[[volume]]
|
|
||||||
source = "/home/me/Downloads"
|
|
||||||
target = "/Downloads"
|
|
||||||
read_only = true
|
|
||||||
|
|
||||||
[proxy] # optional
|
|
||||||
address = "haze.example.com" # base domain
|
|
||||||
https = true # Whether the instances are reachable over https
|
|
||||||
listen = "/run/haze/haze.sock" # either a unix socket path
|
|
||||||
#listen = "127.0.0.1:8080" # or a socket address
|
|
||||||
cert = "/path/to/haze.test.crt" # optional - PEM encoded certificate chain
|
|
||||||
key = "/path/to/haze.test.key" # optional - PEM encoded private key
|
|
||||||
|
|
||||||
# presets allow for easy usage of commonly used setups
|
|
||||||
[[preset]]
|
|
||||||
name = "groupfolders" # name of the preset
|
|
||||||
apps = ["groupfolders"] # app to enable
|
|
||||||
commands = ["occ groupfolders:create gf", "occ groupfolders:group 1 admin read write share delete"] # commands to run post-setup
|
|
||||||
```
|
|
||||||
|
|
||||||
## Xdebug
|
|
||||||
|
|
||||||
Haze Xdebug is running in a docker container, you need to tell you IDE how to
|
|
||||||
properly map the path. The IDE debugger config usually looks like:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"label": "PHP: Debug server within docker",
|
|
||||||
"adapter": "Xdebug",
|
|
||||||
"request": "launch",
|
|
||||||
"port": 9003,
|
|
||||||
"pathMappings": {
|
|
||||||
"/var/www/html": "<sources_root_configured_in_haze.toml>",
|
|
||||||
"/var/www/html/apps-extra": "<app_directories_configured_in_haze.toml>",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
This would have to be adapted for detached instances.
|
|
||||||
|
|
||||||
To enable Xdebug for all requests:
|
|
||||||
|
|
||||||
- Uncomment the lines in `haze <cloud-id> edit /config/php.ini`
|
|
||||||
- Then run `haze reload <cloud-id>`
|
|
||||||
|
|
||||||
## FrankenPHP (experimental)
|
|
||||||
|
|
||||||
You can have Nextcloud run on FrankenPHP.
|
|
||||||
|
|
||||||
Caddy's admin metrics are then accessible through
|
|
||||||
`http://<cloud-id>-franken-php.haze.test`. With ember you can run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ember --addr http://<cloud-id>-franken-php.haze.test
|
|
||||||
```
|
|
||||||
|
|
|
||||||
1
book/.gitignore
vendored
Normal file
1
book/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
book
|
||||||
4
book/book.toml
Normal file
4
book/book.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
[book]
|
||||||
|
title = "Haze"
|
||||||
|
authors = ["Robin Appelman"]
|
||||||
|
language = "en"
|
||||||
30
book/src/README.md
Normal file
30
book/src/README.md
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Haze
|
||||||
|
|
||||||
|
Hazy with a chance of clouds.
|
||||||
|
|
||||||
|
`haze` is a tool that provides provides an easy way to set up Nextcloud test
|
||||||
|
instances with a choice of php version, database server, optional s3 or ldap
|
||||||
|
setup and much more.
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
- Grab a binary from the
|
||||||
|
[Codeberg releases](https://codeberg.org/icewind/haze/releases) and place it
|
||||||
|
in your `$PATH`
|
||||||
|
|
||||||
|
- Create a file `~/.config/haze/haze.toml` with the following content:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
sources_root = "/path/to/nextcloud/sources"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Start a basic Nextcloud instance:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze start
|
||||||
|
```
|
||||||
|
|
||||||
|
- Navigate to the address that is provided in the output.
|
||||||
|
|
||||||
|
See the [setup](./setup.html), [configuration](./configuration.html) and
|
||||||
|
[usage](./usage.html) for a more details.
|
||||||
15
book/src/SUMMARY.md
Normal file
15
book/src/SUMMARY.md
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Summary
|
||||||
|
|
||||||
|
[Introduction](README.md)
|
||||||
|
|
||||||
|
- [Setup](setup.md)
|
||||||
|
- [Usage](usage.md)
|
||||||
|
- [Configuration](configuration.md)
|
||||||
|
- [Proxy](proxy/README.md)
|
||||||
|
- [DNS](proxy/dns.md)
|
||||||
|
- [HTTPS](proxy/https.md)
|
||||||
|
- [Services](services.md)
|
||||||
|
- [Federation](federation.md)
|
||||||
|
- [Haze scripts](scripts.md)
|
||||||
|
- [Xdebug](xdebug.md)
|
||||||
|
- [FrankenPHP (experimental)](frankenphp.md)
|
||||||
272
book/src/configuration.md
Normal file
272
book/src/configuration.md
Normal file
|
|
@ -0,0 +1,272 @@
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
Configuration is loaded from `~/.config/haze/haze.toml`.
|
||||||
|
|
||||||
|
The minimum required configuration needed to get started is just the
|
||||||
|
`sources_root` options.
|
||||||
|
|
||||||
|
The full list of supported options is:
|
||||||
|
|
||||||
|
### sources_root
|
||||||
|
|
||||||
|
The local path of the nextcloud sources. This options is **required**.
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
### app_directories
|
||||||
|
|
||||||
|
A list of additional app directory paths to look for apps into
|
||||||
|
|
||||||
|
Default `[]`
|
||||||
|
|
||||||
|
Type: list of strings
|
||||||
|
|
||||||
|
### work_dir
|
||||||
|
|
||||||
|
The location where haze keeps it's temporary files and caches
|
||||||
|
|
||||||
|
Default: `/tmp/haze`
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
### worktree_dir
|
||||||
|
|
||||||
|
The location to to store git worktrees when using instances with detached
|
||||||
|
sources.
|
||||||
|
|
||||||
|
Default: `<work_dir>/worktrees`
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
## auto_setup
|
||||||
|
|
||||||
|
Options for automatically setting up the newly created Nextcloud instance.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[auto_setup]
|
||||||
|
username = "foo"
|
||||||
|
password = "bar"
|
||||||
|
enable_apps = ["files_external"]
|
||||||
|
disable_apps = ["contacts"]
|
||||||
|
post_setup = [
|
||||||
|
"occ group:add test",
|
||||||
|
]
|
||||||
|
config = { "enforce_theme" = "dark" }
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[auto_setup]
|
||||||
|
enabled = false
|
||||||
|
```
|
||||||
|
|
||||||
|
### auto_setup.enabled
|
||||||
|
|
||||||
|
Whether to automatically setup Nextcloud inside a created instance.
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Type: boolean
|
||||||
|
|
||||||
|
### auto_setup.username
|
||||||
|
|
||||||
|
The username to use for the admin account during auto setup.
|
||||||
|
|
||||||
|
Default: `admin`
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
### auto_setup.password
|
||||||
|
|
||||||
|
The password to use for the admin account during auto setup.
|
||||||
|
|
||||||
|
Default: `admin`
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
### auto_setup.enabled_apps
|
||||||
|
|
||||||
|
Extra apps to enable after auto setup
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
Type: list of strings
|
||||||
|
|
||||||
|
### auto_setup.disabled_apps
|
||||||
|
|
||||||
|
Apps to disabled after auto setup
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
Type: list of strings
|
||||||
|
|
||||||
|
### auto_setup.post_setup
|
||||||
|
|
||||||
|
Commands to execute after auto setup
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
Type: list of strings
|
||||||
|
|
||||||
|
### auto_setup.config
|
||||||
|
|
||||||
|
System configuration options to set before auto setup
|
||||||
|
|
||||||
|
Default: `{}`
|
||||||
|
|
||||||
|
Type: Object
|
||||||
|
|
||||||
|
## volume
|
||||||
|
|
||||||
|
Additional files or directories to bind-mount into instances.
|
||||||
|
|
||||||
|
Any number of volume options can be configured
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[volume]]
|
||||||
|
source = "/tmp/haze-shared"
|
||||||
|
target = "/shared"
|
||||||
|
create = true
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[volume]]
|
||||||
|
source = "/home/me/Downloads"
|
||||||
|
target = "/Downloads"
|
||||||
|
read_only = true
|
||||||
|
```
|
||||||
|
|
||||||
|
### volume.source
|
||||||
|
|
||||||
|
The source path on the host
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
### volume.target
|
||||||
|
|
||||||
|
The target path inside the container
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
### volume.create
|
||||||
|
|
||||||
|
Create the source directory on the host if it doesn't exist already.
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: boolean
|
||||||
|
|
||||||
|
### volume.read_only
|
||||||
|
|
||||||
|
Whether to mount the file or directory as read read_only
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: boolean
|
||||||
|
|
||||||
|
### preset
|
||||||
|
|
||||||
|
Configured presets that can be used when creating instances.
|
||||||
|
|
||||||
|
Any number of presets can be configured.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[preset]]
|
||||||
|
name = "groupfolders"
|
||||||
|
apps = ["groupfolders"]
|
||||||
|
commands = [
|
||||||
|
"occ groupfolders:create gf",
|
||||||
|
"occ groupfolders:group 1 admin read write share delete"
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### preset.name
|
||||||
|
|
||||||
|
The name of the preset, this is used when creating instances to select the
|
||||||
|
preset.
|
||||||
|
|
||||||
|
Type: string without whitespace
|
||||||
|
|
||||||
|
### preset.apps
|
||||||
|
|
||||||
|
A list of apps to enable when the preset is used.
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
Type: list of strings
|
||||||
|
|
||||||
|
### preset.commands
|
||||||
|
|
||||||
|
A list of commands to run post-setup when the preset is used.
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
Type: list of strings
|
||||||
|
|
||||||
|
## proxy
|
||||||
|
|
||||||
|
Configuration for the haze proxy. Only required when using the proxy.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[proxy]
|
||||||
|
address = "haze.example.com"
|
||||||
|
listen = "/run/haze/haze.sock"
|
||||||
|
https = true
|
||||||
|
cert = "/path/to/haze.test.crt"
|
||||||
|
key = "/path/to/haze.test.key"
|
||||||
|
```
|
||||||
|
|
||||||
|
### proxy.listen
|
||||||
|
|
||||||
|
The ip and port or unix socket for the proxy to listen on.
|
||||||
|
|
||||||
|
**Required** when the proxy is enabled.
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
listen = "/run/haze/haze.sock"
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml
|
||||||
|
listen = "127.0.0.1:8080"
|
||||||
|
```
|
||||||
|
|
||||||
|
### proxy.address
|
||||||
|
|
||||||
|
The base domain the proxy is accessible on.
|
||||||
|
|
||||||
|
**Required** if the proxy is enabled.
|
||||||
|
|
||||||
|
Type: string
|
||||||
|
|
||||||
|
### proxy.https
|
||||||
|
|
||||||
|
Whether to enable built-in https support for the proxy.
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Type: boolean
|
||||||
|
|
||||||
|
### proxy.cert
|
||||||
|
|
||||||
|
The path of the PEM encoded certificate chain to use for https.
|
||||||
|
|
||||||
|
**Required** if https is enabled for the proxy.
|
||||||
|
|
||||||
|
Type: string.
|
||||||
|
|
||||||
|
### proxy.cert
|
||||||
|
|
||||||
|
The path of the PEM encoded private key to use for https.
|
||||||
|
|
||||||
|
**Required** if https is enabled for the proxy.
|
||||||
|
|
||||||
|
Type: string.
|
||||||
13
book/src/federation.md
Normal file
13
book/src/federation.md
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Federation
|
||||||
|
|
||||||
|
Multiple instances can reach each other by using their instance name as domain
|
||||||
|
name to allow for testing federation between instances.
|
||||||
|
|
||||||
|
For example, if you have a `rover-beavers` and `splendid-couch` instance, you
|
||||||
|
can create a federated share from the `rover-beavers` instance to
|
||||||
|
`http://admin@splendid-couch`.
|
||||||
|
|
||||||
|
If the proxy is setup with https, you can use https between the instances by
|
||||||
|
using the full proxy urls.
|
||||||
|
|
||||||
|
For example sharing to `admin@splendid-couch.haze.example.com`.
|
||||||
11
book/src/frankenphp.md
Normal file
11
book/src/frankenphp.md
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# FrankenPHP (experimental)
|
||||||
|
|
||||||
|
You can have Nextcloud run on FrankenPHP by starting the instance with the
|
||||||
|
`franken-php` option.
|
||||||
|
|
||||||
|
Caddy's admin metrics are then accessible through
|
||||||
|
`http://<cloud-id>-franken-php.haze.test`. With ember you can run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ember --addr http://<cloud-id>-franken-php.haze.test
|
||||||
|
```
|
||||||
91
book/src/proxy/README.md
Normal file
91
book/src/proxy/README.md
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
# Proxy
|
||||||
|
|
||||||
|
By default, instances can be accessed by their IP. In order to get more
|
||||||
|
memorable URLs and allow supporting https. haze comes with a builtin reverse
|
||||||
|
proxy to allow using a wildcard domain.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- [Setup a DNS record](./dns.html) for `*.haze.example.com` and
|
||||||
|
`haze.example.com` pointing to your development machine.
|
||||||
|
- Set the `proxy` configuration with your domain and desired listen endpoint.
|
||||||
|
- Set up a service to run `haze proxy` in the background as your own user. A
|
||||||
|
systemd user service is recommended (see
|
||||||
|
[haze.service](<[./haze.service](https://codeberg.org/icewind/haze/src/branch/main/haze.service)>)
|
||||||
|
for an example).
|
||||||
|
- If you're already running a reverse proxy, configure your reverse proxy of
|
||||||
|
choice to proxy `*.haze.example.com` and `haze.example.com` to the proxy's
|
||||||
|
listen endpoint.
|
||||||
|
- (Optionally) [setup https](./https.html) for the proxy.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Add the following configuration to the `haze.toml` config file:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[proxy]
|
||||||
|
address = "haze.example.com" # the base domain for the proxy to use
|
||||||
|
listen = "127.0.0.1:8080" # the port+ip to listen on
|
||||||
|
# listen = "/var/run/haze/haze.sock" # or a unix socket path
|
||||||
|
```
|
||||||
|
|
||||||
|
### Without a reverse proxy
|
||||||
|
|
||||||
|
If you have no other http(s) servers on your development machine, you can setup
|
||||||
|
things without a reverse proxy.
|
||||||
|
|
||||||
|
Simply configure the proxy to listen on port `80` (or `443` when using http).
|
||||||
|
|
||||||
|
Binding to port 80 or443 as a regular user requires either giving the haze
|
||||||
|
binary the `net_bind_service` capability with
|
||||||
|
`sudo setcap cap_net_bind_service=+ep $(which haze)` (this will have to be done
|
||||||
|
every time your upgrade haze) or configure your system to allow unpriviled users
|
||||||
|
to bind on the low port numbers. Using
|
||||||
|
`sysctl net.ipv4.ip_unprivileged_port_start=80` and writing
|
||||||
|
|
||||||
|
```
|
||||||
|
net.ipv4.ip_unprivileged_port_start=80
|
||||||
|
```
|
||||||
|
|
||||||
|
to `/etc/sysctl.d/bind.conf` to make it persistent across reboot.
|
||||||
|
|
||||||
|
### With a reverse proxy
|
||||||
|
|
||||||
|
If you're already have other http(s) services listening on your machine, you'll
|
||||||
|
probably want to setup a reverse proxy to allow them to all be served on your
|
||||||
|
machine.
|
||||||
|
|
||||||
|
The setup for this will depend on your reverse proxy of the choice, the
|
||||||
|
following example config is for `nginx`.
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
upstream haze-handler {
|
||||||
|
server unix:/var/run/haze/haze.sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name *.haze.example.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://haze-handler;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
When the proxy is configured, generated URLs for the instances will use a
|
||||||
|
subdomain of the configured domain, e.g. the `rolling-bees` instance will be
|
||||||
|
available at `rolling-bees.haze.example.com`. Additionally, `haze.example.com`
|
||||||
|
will automatically point to the last created instance.
|
||||||
|
|
||||||
|
Additionally, the proxy allows access to the service containers trough either
|
||||||
|
`<instance id>-<service id>.haze.example.com` for a specific instance, or
|
||||||
|
`<service-id>.haze.example.com` for the last created instance. For example
|
||||||
|
`rolling-bees-mail.haze.example.com` will give access to the smtp4dev web
|
||||||
|
interface of the `rolling-bees` instance.
|
||||||
27
book/src/proxy/dns.md
Normal file
27
book/src/proxy/dns.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# DNS
|
||||||
|
|
||||||
|
Since the domain name used for the instance is dynamic, a wildcard dns record is
|
||||||
|
required.
|
||||||
|
|
||||||
|
## With your domain's DNS provider
|
||||||
|
|
||||||
|
If you own a domain you would like to use, you can create a wildcard domain
|
||||||
|
withing the DNS settings of your DNS provider. For example creating a record an
|
||||||
|
`A` record for `*.haze.example.com` with a value of `127.0.0.1` and a similar
|
||||||
|
one for `haze.example.com`.
|
||||||
|
|
||||||
|
## With a local dnsmasq
|
||||||
|
|
||||||
|
If you do not own a "real" domain for using with haze, you can setup `dnsmasq`
|
||||||
|
locally to achieve the same goal instead.
|
||||||
|
|
||||||
|
How to install and enable `dnsmasq` will depend on your distro of choice and
|
||||||
|
should be documented by it's documentation.
|
||||||
|
|
||||||
|
Once setup, a configuration line like
|
||||||
|
|
||||||
|
```
|
||||||
|
address=/haze.local/172.0.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
should be enough to point `haze.local` and `*.haze.local` to your local host.
|
||||||
78
book/src/proxy/https.md
Normal file
78
book/src/proxy/https.md
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
# HTTPS
|
||||||
|
|
||||||
|
The proxy can be setup to enable using https to access the running instances.
|
||||||
|
Besides the warm and fuzy feeling of knowing that nobody can snoop on the trafic
|
||||||
|
that is happening completely local inside your machine. Accessing the page over
|
||||||
|
https is required for some javascript features (such as service workers), as
|
||||||
|
they are only available in "secure contexts".
|
||||||
|
|
||||||
|
## Getting a wildcard certificate
|
||||||
|
|
||||||
|
Since the domain name used for the instance is dynamic, a wildcard certificate
|
||||||
|
is required.
|
||||||
|
|
||||||
|
## Let's encrypt
|
||||||
|
|
||||||
|
Let's encrypt allows getting trusted wildcard certificates for free if you can
|
||||||
|
use DNS validation.
|
||||||
|
|
||||||
|
How to setup DNS validation will depend on the specifics of the DNS provider and
|
||||||
|
ACME client.
|
||||||
|
[This](https://community.letsencrypt.org/t/dns-providers-who-easily-integrate-with-lets-encrypt-dns-validation/86438)
|
||||||
|
lists some DNS providers and supported ACME clients.
|
||||||
|
|
||||||
|
## Self signed
|
||||||
|
|
||||||
|
You can also create a self-signed wildcard certificate using a tool like
|
||||||
|
`mkcert`. This certificate will not be trusted by your browser and tools like
|
||||||
|
curl, but you can add manually add it to the trusted certificates on your
|
||||||
|
system, or bypass the certficate warning in the browser/curl every time.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate local wildcard certificate
|
||||||
|
mkcert -cert-file <path-to-your-certificats>haze.example.com.crt -key-file <path-to-your-certificats>haze.example.com.key '*.haze.example.com'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using the certificate
|
||||||
|
|
||||||
|
### Without reverse proxy
|
||||||
|
|
||||||
|
The haze proxy can serve over https directly, to enable that add the following
|
||||||
|
to the `[proxy]` section of your `haze.toml`.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
https = true
|
||||||
|
cert = "/path/to/haze.example.com.crt"
|
||||||
|
key = "/path/to/haze.example.com.key"
|
||||||
|
```
|
||||||
|
|
||||||
|
You might also want to change the port it's listening on to `443`.
|
||||||
|
|
||||||
|
### With a reverse proxy
|
||||||
|
|
||||||
|
This depends on what reverse proxy you have setup. The following example is for
|
||||||
|
`nginx`.
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
upstream haze-handler {
|
||||||
|
server unix:/run/haze/haze.sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen 443 ssl;
|
||||||
|
http2 on;
|
||||||
|
server_name *.haze.example.com;
|
||||||
|
|
||||||
|
ssl_certificate <path-to-your-certificats>/haze.example.com.crt;
|
||||||
|
ssl_certificate_key <path-to-your-certificats>/haze.example.com.key;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://haze-handler;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
72
book/src/scripts.md
Normal file
72
book/src/scripts.md
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
# Haze scripts
|
||||||
|
|
||||||
|
Haze scripts combine a set of instance options and a script to run in the
|
||||||
|
instance.
|
||||||
|
|
||||||
|
Haze scripts are intended to way to create automated ways of running more
|
||||||
|
complex tests are setting up more complex instances.
|
||||||
|
|
||||||
|
A script contains of 3 paths
|
||||||
|
|
||||||
|
1. An optional shebang line setting `haze` as the interpreter, e.g.
|
||||||
|
`#! /usr/bin/env -S haze script`
|
||||||
|
2. A shebang line setting the options for the instance creation as the
|
||||||
|
interpreter, e.g. `#! haze shell pgsql s3`
|
||||||
|
3. The rest that is ran as a script inside the created instance.
|
||||||
|
|
||||||
|
The first sheband is set, the script can be ran directly. Else it needs to be
|
||||||
|
run with `haze script [path-to-script]`.
|
||||||
|
|
||||||
|
For example, the following script will create an instance with `postgresql` and
|
||||||
|
`s3` primary storage. Then creates a new file, gets the file id, read the object
|
||||||
|
of the file from S3, validate that it contains the expected contents, and
|
||||||
|
cleanup the instance.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#! #! /usr/bin/env -S haze script
|
||||||
|
#! haze shell pgsql s3
|
||||||
|
|
||||||
|
echo 'test' | occ file:put '-' /admin/files/test.txt
|
||||||
|
FILE_ID=$(occ info:file /admin/files/test.txt | grep fileid: | grep -oE '[0-9]+')
|
||||||
|
OBJECT_CONTENTS=$(occ file:object:get urn:oid:$FILE_ID -)
|
||||||
|
if [ "$OBJECT_CONTENTS" == 'test' ]; then
|
||||||
|
echo "object contains expected contents"
|
||||||
|
else
|
||||||
|
echo "object does not contains expected contents!"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Script modes
|
||||||
|
|
||||||
|
Scripts can be either `shell` or `start` scripts.
|
||||||
|
|
||||||
|
`shell` scripts will automatically remove the created instance once the script
|
||||||
|
is done, just like `haze shell` will. The intended use case for this is
|
||||||
|
performing some tests in the created instance without leaving state behind.
|
||||||
|
|
||||||
|
`start` scripts on the other hand will keep the instance, like `haze start`
|
||||||
|
will. The intended use case for this is creating more complex instances without
|
||||||
|
having to configure a dedicated preset.
|
||||||
|
|
||||||
|
The script mode is determined based on the shebang line. The mode set in a
|
||||||
|
script can be overriden by running the script with
|
||||||
|
`haze script [shell|start] path-to-script.sh`.
|
||||||
|
|
||||||
|
## Using different interpreters
|
||||||
|
|
||||||
|
By default, the script contents are executed as either `bash` script, or `nu`
|
||||||
|
script based on the extension.
|
||||||
|
|
||||||
|
You can overwrite the interpreter used to execute the script by adding an extra
|
||||||
|
`#!` line to the script, for example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#! /usr/bin/env -S haze script
|
||||||
|
#! haze shell pgsql s3
|
||||||
|
#! php -f
|
||||||
|
<?php
|
||||||
|
print("Hello");
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the interpreter used needs to already be available inside the haze
|
||||||
|
container.
|
||||||
41
book/src/services.md
Normal file
41
book/src/services.md
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
# Services
|
||||||
|
|
||||||
|
The following service options are available:
|
||||||
|
|
||||||
|
- `s3`: set up an S3 server and configure to Nextcloud to use it as primary
|
||||||
|
storage.
|
||||||
|
- `s3s`: enable TLS for the S3 setup.
|
||||||
|
- `s3mb`: enable multi-bucket S3 setup.
|
||||||
|
- `s3m`: enable multi-instance S3 setup.
|
||||||
|
- `ldap`: set up an LDAP server.
|
||||||
|
- `saml`: set up authentik as a SAML IDP.
|
||||||
|
- `oidc`: set up authentik as an OIDC IDP.
|
||||||
|
- `scim`: set up authentik as a SCIM server.
|
||||||
|
- `office`: set up a Nextcloud Office server.
|
||||||
|
- `onlyoffice` setup an onlyoffice document server.
|
||||||
|
- `push` set up [client push](https://github.com/nextcloud/notify_push).
|
||||||
|
- `smb`: set up a samba server for external storage use.
|
||||||
|
- `dav`: set up a WebDAV server for external storage use.
|
||||||
|
- `sftp`: set up a SFTP server for external storage use.
|
||||||
|
- `sftp-key`: set up a SFTP server for external storage use with public key
|
||||||
|
authentication.
|
||||||
|
- `kaspersky`: set up a kaspersky scan engine server in http mode. ( Requires
|
||||||
|
[manually setting up the image](https://github.com/icewind1991/kaspersky-docker))
|
||||||
|
- `kaspersky-icap`: setup a kaspersky scan engine server in ICAP mode.
|
||||||
|
- `clamav`: set up a local clam av scanner in executable mode.
|
||||||
|
- `clamav-socket`: set up a clam av scanner in socket mode.
|
||||||
|
- `clamav-icap`: set up a clam av scanner in ICAP mode.
|
||||||
|
- `clamav-icap-tls`: set up a clam av scanner in ICAP mode with TLS encryption.
|
||||||
|
- `oc`: start an ownCloud instance in the same network.
|
||||||
|
- `imaginary`: start an Imaginary service and configure it for preview
|
||||||
|
generation.
|
||||||
|
- `mail`: start a [smtp4dev](https://github.com/rnwood/smtp4dev) server and
|
||||||
|
configure it the mail server.
|
||||||
|
- `webhook` start a
|
||||||
|
[webhook tester](https://github.com/tarampampam/webhook-tester)
|
||||||
|
- `redis`: start a separate container for redis.
|
||||||
|
- `redis-tls`: connect to redis over TLS.
|
||||||
|
- `<path to app.tar.gz>`: by specifying the path to an app package this package
|
||||||
|
will be extracted into the apps. directory of the new instance (overwriting
|
||||||
|
any existing app code). This can be used to quickly test a packaged app.
|
||||||
|
- The name of any configured preset.
|
||||||
36
book/src/setup.md
Normal file
36
book/src/setup.md
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Setup
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Docker
|
||||||
|
|
||||||
|
haze is built around docker containers and manages containers using the docker
|
||||||
|
socket. Using podman with docker compatibility might also work, but is untested.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
- Grab a binary from the
|
||||||
|
[Codeberg releases](https://codeberg.org/icewind/haze/releases) and place it
|
||||||
|
in your `$PATH`
|
||||||
|
|
||||||
|
## Config
|
||||||
|
|
||||||
|
Create a file `~/.config/haze/haze.toml` with the following options:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
sources_root = "/path/to/nextcloud/sources"
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [configuration section](./configuration.html) for more options.
|
||||||
|
|
||||||
|
## Test the Setup
|
||||||
|
|
||||||
|
### Quick examples
|
||||||
|
|
||||||
|
- Start a basic Nextcloud instance:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze start
|
||||||
|
```
|
||||||
|
|
||||||
|
- Navigate to the address that is provided in the output.
|
||||||
230
book/src/usage.md
Normal file
230
book/src/usage.md
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
## Quick examples
|
||||||
|
|
||||||
|
- Start a Nextcloud instance with `postgresql`, and `s3` primary storage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze start pgsql s3
|
||||||
|
```
|
||||||
|
|
||||||
|
- Start a Nextcloud instance with `sqlite`, `php 8.3` and an `smb` external
|
||||||
|
storage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze start 8.3 smb
|
||||||
|
```
|
||||||
|
|
||||||
|
- Run specific units test against an `oracle` database
|
||||||
|
```bash
|
||||||
|
haze test oracle apps/dav/tests/unit/Connector/Sabre
|
||||||
|
```
|
||||||
|
|
||||||
|
## Managing instances
|
||||||
|
|
||||||
|
### Starting an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze start [--name <name>] [--detach] [database] [php-version] [services] [vX.Y.Z]
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `database` is one of `sqlite`, `mysql`, `mariadb`, `pgsql` or `oracle`
|
||||||
|
with an optional version (e.g. `pgsql:12`), defaults to `sqlite`. And
|
||||||
|
`php-version` is one of `8.0`, `8.1`, `8.2`, `8.3`, `8.4` or `8.5`, defaults to
|
||||||
|
the maximum version support by the current Nextcloud version.
|
||||||
|
|
||||||
|
You can specify a version number (e.g. `v32.0.2`) to use the sources from a
|
||||||
|
release instead of using the local sources.
|
||||||
|
|
||||||
|
Use `--name <name>` to give the instance a specific name instead of a randomly
|
||||||
|
generated one. For example:
|
||||||
|
|
||||||
|
Use `--detach` to give the instance
|
||||||
|
[its own sources](#instances-with-their-own-sources) instead of sharing
|
||||||
|
`sources_root` with all other instances.
|
||||||
|
|
||||||
|
See the [services documentation](./services.html) for a list of available
|
||||||
|
services.
|
||||||
|
|
||||||
|
### List running instances
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] stop
|
||||||
|
```
|
||||||
|
|
||||||
|
### Remove all unpinned running instances
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze clean
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pin an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] pin
|
||||||
|
```
|
||||||
|
|
||||||
|
Pinned instances will not be removed by `haze clean`.
|
||||||
|
|
||||||
|
### Unpin an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] unpin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run commands in a temporary instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze shell [database] [php-version] [services] [cmd]
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create an instance, run the provided command, and cleanup the
|
||||||
|
instance.
|
||||||
|
|
||||||
|
If no `cmd` is specified it will launch `bash`
|
||||||
|
|
||||||
|
## Run tests in a new instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze test [database] [php-version] [services] [phpunit version] [path]
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `path` is a file or folder to run PHPUnit in, relative to the sources
|
||||||
|
root.
|
||||||
|
|
||||||
|
This will create a fresh instance, run the PHPUnit tests, and clean up the
|
||||||
|
created instance.
|
||||||
|
|
||||||
|
## Interacting with running instances
|
||||||
|
|
||||||
|
The following commands run against the most recently started instance by default
|
||||||
|
and allow optionally providing a `match` to select a specific instance by its
|
||||||
|
name.
|
||||||
|
|
||||||
|
### Open an instance in the browser
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] open
|
||||||
|
```
|
||||||
|
|
||||||
|
### Execute a command on an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] [service] [cmd]
|
||||||
|
```
|
||||||
|
|
||||||
|
If no `cmd` is specified it will launch `bash`
|
||||||
|
|
||||||
|
If a service name or `db` is provided, the command will be in the container of
|
||||||
|
the service or database.
|
||||||
|
|
||||||
|
If no `cmd` is specified it will launch `bash`
|
||||||
|
|
||||||
|
### Execute an occ command on an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] occ [cmd]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connect to the database on an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] db
|
||||||
|
```
|
||||||
|
|
||||||
|
### Show the logs of an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Edit a file in an instance with the local $EDITOR
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] edit <path>
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `<path>` is the path of a file inside the container, for example
|
||||||
|
`config/config.php`.
|
||||||
|
|
||||||
|
### Reload the php config of an instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] reload
|
||||||
|
```
|
||||||
|
|
||||||
|
The php configuration can edit changed with `haze edit /config/php.ini`
|
||||||
|
|
||||||
|
### Run a command with instance environment variables set
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze [match] env <cmd> [args]
|
||||||
|
```
|
||||||
|
|
||||||
|
Runs the provided command with `NEXTCLOUD_URL`, `DATABASE_URL` and `REDIS_URL`
|
||||||
|
environment variables set for the matched instance.
|
||||||
|
|
||||||
|
This is intended to run a local
|
||||||
|
[push daemon](https://github.com/nextcloud/notify_push) against an instance.
|
||||||
|
|
||||||
|
## Git tools
|
||||||
|
|
||||||
|
Haze provides a couple of utilities to make working with many git repositories
|
||||||
|
for apps easier.
|
||||||
|
|
||||||
|
### Checkout a branch for all local apps
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze git checkout [branch]
|
||||||
|
```
|
||||||
|
|
||||||
|
Checks out the branch in all git repositories within the apps folder.
|
||||||
|
|
||||||
|
Defaults to the branch matching the current checked out server versions (e.g.
|
||||||
|
`master` or `stable33`).
|
||||||
|
|
||||||
|
`master` and `main` can be used interchangeably.
|
||||||
|
|
||||||
|
### Pull remote changes for all local apps
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze git pull
|
||||||
|
```
|
||||||
|
|
||||||
|
Performs a pull in all git repositories within the apps folder.
|
||||||
|
|
||||||
|
## Update the container images
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze update
|
||||||
|
```
|
||||||
|
|
||||||
|
## Instances with their own sources
|
||||||
|
|
||||||
|
By default every instance shares the sources configured as `sources_root`, so
|
||||||
|
all instances always run the same code. An instance started with `--detach` gets
|
||||||
|
its own `git worktree` of `sources_root` instead, created in `worktree_dir`,
|
||||||
|
which lets you run several instances on different branches at the same time.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
haze start --name my-fix --detach
|
||||||
|
```
|
||||||
|
|
||||||
|
The worktree is checked out with a detached head. Every app in one of the
|
||||||
|
`app_directories` that gets enabled during setup receives its own worktree as
|
||||||
|
well, other apps keep running from the shared app directory.
|
||||||
|
|
||||||
|
The worktrees are removed together with the instance, by `haze stop` or
|
||||||
|
`haze clean`.
|
||||||
31
book/src/xdebug.md
Normal file
31
book/src/xdebug.md
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Xdebug
|
||||||
|
|
||||||
|
To use Xdebug running in a haze instance with your IDE for debugging, you need
|
||||||
|
to tell you IDE how to properly map the path from the container to the host. The
|
||||||
|
IDE debugger config usually looks like:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"label": "PHP: Debug server within docker",
|
||||||
|
"adapter": "Xdebug",
|
||||||
|
"request": "launch",
|
||||||
|
"port": 9003,
|
||||||
|
"pathMappings": {
|
||||||
|
"/var/www/html": "<sources_root_configured_in_haze.toml>",
|
||||||
|
"/var/www/html/apps-extra": "<app_directories_configured_in_haze.toml>",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
This would have to be adapted for detached instances.
|
||||||
|
|
||||||
|
### Debugging all requests
|
||||||
|
|
||||||
|
By default, xdebug is configured to only run for requests that containing the
|
||||||
|
trigger (e.g. from using the xdebug browser extension, or adding
|
||||||
|
`?XDEBUG_SESSION_START=1` to the url).
|
||||||
|
|
||||||
|
To enable Xdebug for all requests:
|
||||||
|
|
||||||
|
- Uncomment the lines in `haze [cloud-id] edit /config/php.ini`
|
||||||
|
- Then run `haze reload [cloud-id]`
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
"haze-image-php-8.2" = pkgs: pkgs.haze-image-php-82;
|
"haze-image-php-8.2" = pkgs: pkgs.haze-image-php-82;
|
||||||
"haze-image-php-8.1" = pkgs: pkgs.haze-image-php-81;
|
"haze-image-php-8.1" = pkgs: pkgs.haze-image-php-81;
|
||||||
"haze-image-php-8.0" = pkgs: pkgs.haze-image-php-80;
|
"haze-image-php-8.0" = pkgs: pkgs.haze-image-php-80;
|
||||||
|
haze-book = pkgs: pkgs.haze-book;
|
||||||
};
|
};
|
||||||
|
|
||||||
tools = pkgs:
|
tools = pkgs:
|
||||||
|
|
@ -63,6 +64,7 @@
|
||||||
bacon
|
bacon
|
||||||
skopeo
|
skopeo
|
||||||
dive
|
dive
|
||||||
|
mdbook
|
||||||
];
|
];
|
||||||
|
|
||||||
homeModules = {
|
homeModules = {
|
||||||
|
|
|
||||||
20
nix/book.nix
Normal file
20
nix/book.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
mdbook,
|
||||||
|
stdenv,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "haze-book";
|
||||||
|
src = ../book;
|
||||||
|
|
||||||
|
nativeBuildInputs = [mdbook];
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
mdbook build
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r book/* $out/
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
@ -6,4 +6,5 @@ final: prev: {
|
||||||
haze-image-php-82 = final.callPackage ./image/haze.nix {php = final.php82;};
|
haze-image-php-82 = final.callPackage ./image/haze.nix {php = final.php82;};
|
||||||
haze-image-php-81 = final.callPackage ./image/haze.nix {php = final.php81;};
|
haze-image-php-81 = final.callPackage ./image/haze.nix {php = final.php81;};
|
||||||
haze-image-php-80 = final.callPackage ./image/haze.nix {php = final.php80;};
|
haze-image-php-80 = final.callPackage ./image/haze.nix {php = final.php80;};
|
||||||
|
haze-book = final.callPackage ./book.nix {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue