Hubzilla in the pasture
Hubzilla 11.4.1 with its pubcrawl addon (peers/hubzilla.sh): the hlhd image on the shared MySQL, a cron sidecar, hzuser
and hzfriend made through Hubzilla's own PHP as public channels that speak ActivityPub. scenarios/hubzilla.sh, 20
checks: follows, posts, comments, likes, edits and deletions both ways, and a third channel's comment that the thread's
owner passes on, which PrivaPub takes on its FEP-8b32 proof. Known gap G-0010 (upstream): Hubzilla 11 keeps a follower
after its Undo{Follow}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
9d0b5fac3e
commit
b39eadffeb
7 files changed
+262
No files matched your search
@@ -0,0 +1,125 @@
|
||||
# Hubzilla 11.4.1: channels with nomadic identity, speaking its own Zot6 and, through its pubcrawl addon, ActivityPub.
|
||||
# The hlhd image (php-fpm and nginx on 8080) on the shared MySQL (database hubzilla, its schema from the image), its
|
||||
# configuration written here and mounted as .htconfig.php, its store in a volume. Its queue runs in processes the web
|
||||
# container spawns and in a cron sidecar (Zotlabs/Daemon/Master.php Cron each minute). It trusts Caddy's CA through the
|
||||
# bundle mounted as its system store. Accounts and channels are made through its own PHP (util/ and cli_startup), and a
|
||||
# channel speaks ActivityPub only once the "Activitypub Protocol" app is installed for it. Its API (api/z/1.0) takes
|
||||
# HTTP Basic authentication by the account's email and password.
|
||||
HUBZILLA_IMAGE=${HUBZILLA_IMAGE:-docker.io/hlhd/hubzilla:v11.4.1}
|
||||
HUBZILLA_PASSWORD=Hubzilla-Pasture-1
|
||||
. "$here/peers/shared.sh"
|
||||
|
||||
hz_php() { podman exec -u www-data -w /var/www/html pasture-hubzilla php "$@"; }
|
||||
# hz_eval <php>: PHP run inside Hubzilla, its CLI start done (the database, the configuration, the classes)
|
||||
hz_eval() { podman exec -i -u www-data -w /var/www/html pasture-hubzilla php -r "require_once('include/cli_startup.php'); cli_startup(); $1"; }
|
||||
|
||||
hubzilla_config() {
|
||||
cat <<EOF
|
||||
<?php
|
||||
\$db_host = 'mysql';
|
||||
\$db_port = 0;
|
||||
\$db_user = 'pasture';
|
||||
\$db_pass = 'pasture';
|
||||
\$db_data = 'hubzilla';
|
||||
\$db_type = 0;
|
||||
App::\$config['system']['timezone'] = 'UTC';
|
||||
App::\$config['system']['baseurl'] = 'https://hubzilla.test';
|
||||
App::\$config['system']['sitename'] = 'Pasture Hubzilla';
|
||||
App::\$config['system']['location_hash'] = '$(openssl rand -hex 32)';
|
||||
App::\$config['system']['transport_security_header'] = 1;
|
||||
App::\$config['system']['content_security_policy'] = 1;
|
||||
App::\$config['system']['ssl_cookie_protection'] = 1;
|
||||
App::\$config['system']['register_policy'] = REGISTER_OPEN;
|
||||
App::\$config['system']['register_text'] = '';
|
||||
App::\$config['system']['admin_email'] = 'admin@hubzilla.test';
|
||||
App::\$config['system']['verify_email'] = 0;
|
||||
App::\$config['system']['php_path'] = 'php';
|
||||
App::\$config['system']['directory_mode'] = DIRECTORY_MODE_STANDALONE;
|
||||
App::\$config['system']['theme'] = 'redbasic';
|
||||
EOF
|
||||
}
|
||||
|
||||
hubzilla_up() {
|
||||
shared_mysql_up
|
||||
mysql_db hubzilla
|
||||
mkdir -p "$here/.state/hubzilla"
|
||||
[ -s "$here/.state/hubzilla/htconfig.php" ] || hubzilla_config > "$here/.state/hubzilla/htconfig.php"
|
||||
podman volume exists pasture-hubzilla-store || podman volume create --label pasture=1 pasture-hubzilla-store >/dev/null
|
||||
podman run -d --replace --name pasture-hubzilla --network $net --label pasture=1 \
|
||||
-v "$here/.state/hubzilla/htconfig.php:/var/www/html/.htconfig.php:z,ro" -v pasture-hubzilla-store:/var/www/html/store \
|
||||
-v "$ca/bundle.pem:/etc/ssl/certs/ca-certificates.crt:z,ro" "$HUBZILLA_IMAGE" >/dev/null
|
||||
podman exec -u root pasture-hubzilla sh -c 'mkdir -p /var/www/html/store/[data]/smarty3 && chown -R www-data /var/www/html/store'
|
||||
# its schema, once
|
||||
if [ "$(podman exec pasture-mysql mysql -upasture -ppasture -N hubzilla -e "show tables like 'account'" 2>/dev/null)" != "account" ]; then
|
||||
podman exec pasture-hubzilla cat /var/www/html/install/schema_mysql.sql | podman exec -i pasture-mysql mysql -upasture -ppasture hubzilla 2>/dev/null
|
||||
fi
|
||||
for _ in $(seq 1 60); do
|
||||
site hubzilla.test -s -o /dev/null -w '%{http_code}' https://hubzilla.test:6443/.well-known/nodeinfo 2>/dev/null | grep -q 200 && break
|
||||
sleep 2
|
||||
done
|
||||
podman run -d --replace --name pasture-hubzilla-cron --network $net --label pasture=1 --volumes-from pasture-hubzilla \
|
||||
-u www-data -w /var/www/html --entrypoint sh "$HUBZILLA_IMAGE" -c 'while true; do php Zotlabs/Daemon/Master.php Cron; sleep 60; done' >/dev/null
|
||||
hubzilla_settle
|
||||
echo "hubzilla: https://hubzilla.test:6443"
|
||||
}
|
||||
|
||||
# ActivityPub and NodeInfo on, hzuser and hzfriend
|
||||
hubzilla_settle() {
|
||||
hz_php util/addons install pubcrawl >/dev/null 2>&1 || true
|
||||
# NodeInfo is the statistics addon's
|
||||
hz_php util/addons install statistics >/dev/null 2>&1 || true
|
||||
# (the first account is the hub's administrator, as Hubzilla asks)
|
||||
hubzilla_user hzuser 4096
|
||||
hubzilla_user hzfriend
|
||||
}
|
||||
|
||||
# hubzilla_user <nick> [roles]: an account (<nick>@hubzilla.test, the pasture's password; Hubzilla 11 makes accounts
|
||||
# only from its registration queue, so the row is written as that would, the password salted and hashed with whirlpool)
|
||||
# with a public channel of that name that speaks ActivityPub and takes followers without asking. Its role is "public":
|
||||
# Hubzilla 11 grants a connection what a role's perms_connect lists only for public, personal, group and custom, and the
|
||||
# older names its role list still offers ("social") grant nothing, so nobody could post to it
|
||||
hubzilla_user() {
|
||||
hz_eval "
|
||||
require_once('include/account.php'); require_once('include/channel.php');
|
||||
use Zotlabs\Lib\Apps;
|
||||
\$email = '$1@hubzilla.test';
|
||||
\$r = q(\"select account_id from account where account_email = '%s'\", dbesc(\$email));
|
||||
if (! \$r) {
|
||||
\$salt = random_string(32);
|
||||
q(\"insert into account (account_parent, account_salt, account_password, account_email, account_language, account_created, account_flags,
|
||||
account_roles, account_level, account_expires, account_service_class) values (0, '%s', '%s', '%s', 'en', '%s', 0, %d, 5, '%s', '')\",
|
||||
dbesc(\$salt), dbesc(hash('whirlpool', \$salt . '$HUBZILLA_PASSWORD')), dbesc(\$email), dbesc(datetime_convert()), intval(${2:-0}),
|
||||
dbesc(DBA::\$dba->get_null_date()));
|
||||
\$r = q(\"select account_id from account where account_email = '%s'\", dbesc(\$email));
|
||||
}
|
||||
\$account_id = \$r[0]['account_id'];
|
||||
q('update account set account_flags = 0 where account_id = %d', intval(\$account_id));
|
||||
\$c = channelx_by_nick('$1');
|
||||
if (! \$c) {
|
||||
\$x = create_identity(['account_id' => \$account_id, 'nickname' => '$1', 'name' => '$1', 'permissions_role' => 'public', 'publish' => 1]);
|
||||
if (! \$x['success']) { echo 'channel: ' . \$x['message'] . PHP_EOL; exit(1); }
|
||||
\$c = channelx_by_nick('$1');
|
||||
}
|
||||
// (its apps list only what a signed-in channel may have: the import runs as the channel, its session set as
|
||||
// local_channel() reads it)
|
||||
session_id('cli' . \$c['channel_id']);
|
||||
\$_SESSION = ['authenticated' => 1, 'uid' => \$c['channel_id'], 'account_id' => \$c['channel_account_id']];
|
||||
App::\$channel = \$c;
|
||||
Apps::import_system_apps();
|
||||
if (! Apps::addon_app_installed(\$c['channel_id'], 'pubcrawl'))
|
||||
Apps::app_install(\$c['channel_id'], 'Activitypub Protocol');
|
||||
echo 'ok ' . \$c['channel_id'] . PHP_EOL;
|
||||
"
|
||||
}
|
||||
|
||||
# hz_web <nick> <curl args...>: a request to Hubzilla's web pages as <nick>, signed in through its login form (what its
|
||||
# API has no route for: liking, editing, dropping)
|
||||
hz_web() {
|
||||
local nick=$1 jar="$here/.state/hubzilla/$1.cookies"; shift
|
||||
if ! site hubzilla.test -s -b "$jar" https://hubzilla.test:6443/network 2>/dev/null | grep -qi logout; then
|
||||
rm -f "$jar"
|
||||
site hubzilla.test -s -o /dev/null -c "$jar" -X POST https://hubzilla.test:6443/login -d auth-params=login \
|
||||
-d "main_login_username=$nick@hubzilla.test" --data-urlencode "main_login_password=$HUBZILLA_PASSWORD"
|
||||
fi
|
||||
site hubzilla.test -s -b "$jar" -c "$jar" "$@"
|
||||
}
|
||||
Reference in new issue
Block a user