24 KiB
Arcology Project Configuration
- The Arcology's Site List
- Per-site CSS
- Deploy manifests for Arroyo NixOS Generator or your own manifests
- Deploy manifests for a Dynamic Home Manager Configuration
- Service Configuration
- Generator Configuration
- Look don't worry about the rest of these
- Helpers
,#+AUTO_TANGLE: vars:org-babel-default-header-args
This file contains user-configuration. Some sections are generated from org-mode tables if you're meant to be editing or extending them. This is a cool feature of org-babel, where you can use tables as data for code which can output more code or even org headings or links. We use this to generate configuration.
The Arcology's Site List
These can be customized by the user:
title | key | css file | link color |
---|---|---|---|
The Lion's Rear | lionsrear | lionsrear.css | #cfdcc2 |
The Arcology Garden | garden | garden.css | #fcf6ed |
The Complete Computer | cce | cce.css | #dcdcec |
The Arcology Site Engine | arcology | arcology.css | #ccdfff |
Local Dev Environment | localhost | arcology.css | #075192 |
key | domain |
---|---|
lionsrear | thelionsrear.com |
lionsrear | rix.si |
garden | arcology.garden |
garden | whatthefuck.computer |
cce | cce.whatthefuck.computer |
cce | cce.rix.si |
arcology | engine.arcology.garden |
localhost | 127.0.0.1 |
localhost | localhost |
lionsrear | v2.thelionsrear.com |
garden | v2.arcology.garden |
cce | cce2.whatthefuck.computer |
arcology | engine2.arcology.garden |
The Code
Oh we doing some code gen in here, this is just gonna generate some JSON for now joining these two tables lul.
(json-encode
(-map (lambda (siterow)
(pcase-let* ((`(,title ,key ,css ,link) siterow))
`((title . ,title)
(key . ,key)
(css_file . ,(format "arcology/css/%s" css))
(link_color . ,link)
(domains . ,(-map #'cadr
(-filter (pcase-lambda (`(,dkey ,domain))
(equal key dkey))
domains))))))
sites))
That generates JSON that goes in to arcology/settings/sites.json
for the Arcology Seed Command to use:
<<elisp-join-tables()>>
(thread-last domains
(-map (pcase-lambda (`(,site ,domain))
domain))
(s-join ","))
NEXT How to re-seed these if you change the configuration?
for now i just blow away the database but gosh!
Per-site CSS
These are generated from a table, too, because I have brainworms. Note that they're basically the same, but you can customize it further to your satisfaction.
Site | alert | primary | secondary | success | warning | white | gray2 | gray3 | gray4 | black |
---|---|---|---|---|---|---|---|---|---|---|
default-colors | #cc6960 | #707231 | #ebbe7b | #67b4f8 | #7e5c41 | #fcf6ed | #f6e5cb | #baad9b | #82796c | #211f1c |
garden | #cc6960 | #707231 | #ebbe7b | #67b4f8 | #7e5c41 | #fcf6ed | #f6e5cb | #baad9b | #82796c | #211f1c |
lionsrear | #cc6960 | #707231 | #ebbe7b | #67b4f8 | #7e5c41 | #cfdcc2 | #87af87 | #a0aa96 | #82796c | #211f1c |
cce | #cc6960 | #707231 | #ebbe7b | #67b4f8 | #7e5c41 | #fcfcfc | #dcdcec | #cacada | #808090 | #211f1c |
arcology | #cc6960 | #707231 | #ebbe7b | #67b4f8 | #7e5c41 | #fcf6ed | #f6e5cb | #baad9b | #82796c | #211f1c |
The Code
(pcase-let ((`((,name ,alert ,primary ,secondary ,success ,warning ,white ,gray2 ,gray3 , gray4 ,black))
(-filter (lambda (row)
(equal (first row) site))
colors)))
(s-join "\n"
(list ":root {"
(concat " --alert: " alert ";")
(concat " --primary: " primary ";")
(concat " --secondary: " secondary ";")
(concat " --success: " success ";")
(concat " --warning: " warning ";")
(concat " --white: " white ";")
(concat " --light-gray: " gray2 ";")
(concat " --medium-gray: " gray3 ";")
(concat " --dark-gray: " gray4 ";")
(concat " --black: " black ";")
"}")))
<<mk-site-colors(site-colors, "default-colors")>>
<<mk-site-colors(site-colors, "cce")>>
<<mk-site-colors(site-colors, "lionsrear")>>
<<mk-site-colors(site-colors, "garden")>>
<<mk-site-colors(site-colors, "arcology")>>
Deploy manifests for Arroyo NixOS Generator or your own manifests
The Arroyo NixOS Generator will integrate this or you can do this yourself. just import the nixos module above, and then configure it as below:
{ pkgs, ... }:
let
arroyo_rs = pkgs.callPackage /home/rrix/org/arroyo/default.nix {};
arcology = pkgs.callPackage /home/rrix/org/arcology-django/default.nix { inherit arroyo_rs; };
in {
imports = [ ./arcology2-module.nix ];
fileSystems."/media/org" = {
device = "/home/rrix/org";
options = ["bind"];
};
services.arcology-ng = {
enable = true;
packages.arcology = arcology;
domains = pkgs.lib.splitString "," "<<get_allowed_hosts()>>";
orgDir = "/media/org";
folderId = "p1kld-oxnwd";
dataDir = "/srv/arcology";
logLevel = "INFO";
};
}
The NixOS module which defines services.arcology-ng
is in Deploying the Arcology.
NEXT the package import needs to be much better than this.
Deploy manifests for a Dynamic Home Manager Configuration
This deploys A Localhost API for the Arcology to any Home Manager user using systemd
User Units. See LocalAPI Deployment Options for the list of options that can be changed and how to use it:
{ pkgs, ... }:
let
arroyo_rs = pkgs.callPackage /home/rrix/org/arroyo/default.nix {};
arcology = pkgs.callPackage /home/rrix/org/arcology-django/default.nix { inherit arroyo_rs; };
in {
imports = [ ./arcology-localapi-mod.nix ];
services.arcology2 = {
enable = true;
packages.arcology = arcology;
folderId = "p1kld-oxnwd";
environmentFile = "/home/rrix/sync/private-files/.arcology-env";
};
}
NEXT address the callPackages
here…
Service Configuration
these are mostly defaults, a bit of this should be made user-configurable but a lot of this is baked in to how the project works.
Django settings for arcology project.
Generated by 'django-admin startproject' using Django 3.2.22.
For more information on this file, see https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see https://docs.djangoproject.com/en/3.2/ref/settings/
Quick-start development settings - unsuitable for production See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
from pathlib import Path
import os
from .generators import *
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent.parent
DATABASE_PATH = pathlib.Path(os.getenv("ARCOLOGY_DB_PATH", pathlib.Path(os.getcwd()) / "db.sqlite3")).expanduser()
Environment Variables
ARCOLOGY_DJANGO_SECRET
environment variable will be set in the NixOS deployment manifests. this is used for, uhh, security things
SECRET_KEY = os.getenv("ARCOLOGY_DJANGO_SECRET", "devsecret")
Setting ARCOLOGY_ENVIRONMENT=production
in the NixOS deployment manifests will modify a bunch of behavior, probably
ARCOLOGY_ENVIRONMENT = os.getenv("ARCOLOGY_ENVIRONMENT", "dev")
DEBUG = (ARCOLOGY_ENVIRONMENT != "production")
The ARCOLOGY_SYNCTHING_KEY
environment variable will be set to the Syncthing API key, each deployment will need to specify its own, i'll re-think this when it comes time to deploy this to many places.
SYNCTHING_KEY = os.getenv("ARCOLOGY_SYNCTHING_KEY")
The ARCOLOGY_CACHE_PATH
is set to a path that multi-process django can use to cache processed HTML and Atom between processes.
BASE_CACHE_PATH = pathlib.Path(os.environ.get("ARCOLOGY_CACHE_PATH", '/var/tmp/django_cache')).expanduser()
CACHES = {
'default': {
'BACKEND': 'django_prometheus.cache.backends.filebased.FileBasedCache',
'LOCATION': BASE_CACHE_PATH,
},
}
LOCALAPI_BEARER_TOKEN = os.environ.get("ARCOLOGY_LOCALAPI_BEARER_TOKEN", "changeme!")
NEXT Hostname configuration from arcology.model.Site
, eventually
When I have the sites organized in an org-mode table, i'll reapproach the hostname list, and probably before then when i want to test domain-based routing.
ALLOWED_HOSTS = "<<get_allowed_hosts()>>".split(',')
The Arcology is Modular
basically, each org file in this repository, and maybe one or two of your own, are all interoperable and build on top of the base data models of the org docs.
"roam" | Arcology Roam Models |
"arcology" | The Arcology's Data Models and Web Server |
"generators" | The Arroyo Generators |
"syncthonk" | Arcology watchsync Command |
"sitemap" | The Arcology's Site Maps and Discovery Mechanisms |
# Application definition
INSTALLED_APPS = [
<<gen-config-list(arcology_apps)>>
"django_htmx",
"django_prometheus",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
if ARCOLOGY_ENVIRONMENT != "production":
INSTALLED_APPS = ["localapi"] + INSTALLED_APPS
Internationalization
I'll have to do this at some point. what does an internationalized arcology look like, how does one ship translations of this work?
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = True
Logging Configuration
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {
"class": "logging.StreamHandler",
},
},
"loggers": {
"django": {
"handlers": ["console"],
"level": os.getenv("DJANGO_LOG_LEVEL", "INFO"),
"propagate": False,
},
"arcology.cache_decorator": { # left as an example to change later.
"handlers": ["console"],
"level": "DEBUG",
}
},
"root": {
"handlers": ["console"],
"level": os.getenv("ARCOLOGY_LOG_LEVEL", "INFO"),
},
}
Generator Configuration
NEXT directory configuration
import pathlib
import os
ARCOLOGY_BASE_DIR = pathlib.Path(os.environ.get("ARCOLOGY_BASE_DIR", "~/org")).expanduser()
ARCOLOGY_EMACS_SNIPPETS_DIR = str(pathlib.Path("~/org/cce/").expanduser())
ARROYO_BASE_DIR = str(pathlib.Path("~/arroyo-nix").expanduser())
Defining extension modules
It should be feasible to add new data types and models and generators to the Arcology system to fit a user's needs. The defaults are specified here.
These models are only persisted if the page is going to be published and are used by the core The Arcology Web Server to set up the page and render backlinks and tag pages and whatnot.
roam.models.Heading | Arcology Roam Models's heading entity |
roam.models.Reference | Arcology Roam Models's org-roam reference entity |
roam.models.Tag | Arcology Roam Models's heading tag entity |
roam.models.HeadingProperty | Arcology Roam Models's heading properties map |
roam.models.Link | Arcology Roam Models page-to-page links |
arcology.models.Page | The Arcology's Data Models's Page entity |
arcology.models.Feed | The Arcology's Data Models's Feed entity, probably move to its own module some day… |
arcology.models.FeedEntry |
The Arroyo Generators are run regardless of whether a file is published. These are a dictionary so that the user can specify a module when invoking the generate Command">Arcology generate
Command.
emacs | generators.models.EmacsSnippet | |
epkgs | generators.models.EmacsEpkg | |
nixos | generators.models.NixosModule | |
home-manager | generators.models.HomeManagerModule |
The Code
ARCOLOGY_EXTRACTORS = [
<<gen-config-list(arcology_extractors)>>
]
ARROYO_EXTRACTORS = {
<<gen-config-dict(arroyo_extractors)>>
}
Enumerating System Roles
I would like to not need these enumerated here, it seems like it should be easier to add a new role than that. But for now here they are so that the DB seed works better.
server | the Wobserver Configuration with Arroyo Nixos $ |
endpoint | My NixOS configuration |
settop | NixOS Set Top Box |
droid | CCE in Nix On Droid |
waterboy | waterboy icebox'd data collection platform |
ARROYO_ROLES = [
<<gen-config-list(arroyo-roles)>>
]
Roam Allowed Keywords
These tables will be used to create an allowlist of #+KEYWORD
's to store in the database.
These are used to provide system features or power the various generators:
ARCOLOGY_FEED | Add a route that will generate an Atom feed for this page |
ARCOLOGY_KEY | Add a route that will generate an HTML page for this page |
ARCOLOGY_ALLOW_CRAWL | Whether the Arcology page will be marked as allowed in robots.txt |
ARCOLOGY_TOOT_VISIBILITY | This is set to an Mastadan API visibility mode like "public" or "unlisted" |
ARROYO_EMACS_MODULE | Instruct The Arroyo Generators to include an Emacs snippet in the init. |
ARROYO_HOME_MODULE | Instruct The Arroyo Generators to import the referenced home-manager module |
ARROYO_NIXOS_MODULE | Instruct The Arroyo Generators to import the referenced nixos module |
ARROYO_HOME_EPKGS | Instruct The Arroyo Generators to make a custom Emacs-Lisp package available to Arroyo Emacs |
ARROYO_MODULE_WANTS | Define a dependency relationship with the referenced org-roam document (this doc depends on that) |
ARROYO_MODULE_WANTED | Define a dependent relationship from the referenced org-roam document (that doc depends on this) |
ARROYO_SYSTEM_ROLE | Constrain the Nix expressions on the page to only load in this role (can be specified repeatedly) |
ARROYO_SYSTEM_EXCLUDE | Prevent the Nix expressions on the page from loading in the listed role (can be specified repeatedly) |
ARROYO_DIRENV_DIR | Load direnv from a different directory than the loaded buffer's directory. Useful for Org Babel. |
AUTHOR | Used to populate the author in RSS feeds and page metadata |
These are used in some of my custom reports:
BIRTHDAY | Used in People pages. |
LOCATION | Used in People pages. |
PRONOUNS | Used in People pages. |
AGE_OF_MONEY | Used in financial review of Monthly Review |
JPMORGAN | Used in financial review of Monthly Review |
SAVINGS | Used in financial review of Monthly Review |
SPENT_THIS_MONTH | Used in financial review of Monthly Review |
The Code
ROAM_ALLOWED_KEYWORDS = [
<<gen-config-list(roam_allowed_keywords)>>
<<gen-config-list(my_roam_allowed_keywords)>>
# used for deprecated universal-aggregator feed generation
"ARROYO_FEEDS",
"ARROYO_FEED_CATEGORY",
"ARROYO_FEED_URL",
# unused
"CCE_HOME_MODULE",
"ARROYO_EMACS_TANGLED",
"ARROYO_MODULE_DEP",
]
Ignored Roam Tags
Headings with these tags will not be exported.
NOEXPORT |
noexport |
Private |
The Code
IGNORED_ROAM_TAGS = [
<<gen-config-list(ignored_roam_tags)>>
]
Look don't worry about the rest of these
MIDDLEWARE = [
"django_prometheus.middleware.PrometheusBeforeMiddleware",
"django_htmx.middleware.HtmxMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"django_prometheus.middleware.PrometheusAfterMiddleware",
]
ROOT_URLCONF = "arcology.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "arcology.wsgi.application"
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django_prometheus.db.backends.sqlite3",
"NAME": DATABASE_PATH,
}
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
CSRF_TRUSTED_ORIGINS = list(map(lambda it: f"https://{it}", "<<get_allowed_hosts()>>".split(',')))
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = "/static/"
STORAGES = {
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
},
"staticfiles": {
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
},
}
STATICFILES_DIRS = [
BASE_DIR / "arcology/static",
BASE_DIR / "sitemap/static",
]
STATIC_ROOT = os.getenv("ARCOLOGY_STATIC_ROOT", "/var/www/arcology")
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
Helpers
(mapconcat (lambda (row)
(format "\"%s\", # %s\n" (first row) (second row)))
tbl)
(mapconcat (lambda (row)
(format "\"%s\": \"%s\",\n" (first row) (second row)))
tbl)