Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • autinerd/experimental-openwrt-24.10
  • experimental
  • feature/addMikrotikwAP
  • master
  • nrb/airmax-test
  • nrb/ar9344-reset-sequence
  • nrb/ex400-remove-wps
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2019.1-ffs
  • v2019.1.1-ffs
  • v2019.1.2-ffs
  • v2020.1-ffs
  • v2020.1.1-ffs
  • v2020.1.3-ffs
  • v2020.2-ffs
  • v2020.2.1-ffs
  • v2020.2.2-ffs
  • v2020.2.3-ffs
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • v2022.1.1-ffs
  • v2022.1.3-ffs
  • v2022.1.4-ffs
  • v2023.1-ffs
  • v2023.2-ffs
  • v2023.2.2-ffs
  • v2023.2.3-ffs
  • v2023.2.4-ffs
  • v2023.2.5-ffs
  • experimental-2022-09-24
  • experimental-2022-09-24-base
  • experimental-2023-03-11
  • experimental-2023-03-11-base
  • experimental-2023-03-12
  • experimental-2023-03-12-base
  • experimental-2023-03-16
  • experimental-2023-03-16-base
  • experimental-2023-03-20
  • experimental-2023-03-20-base
  • experimental-2023-03-23
  • experimental-2023-03-23-base
  • experimental-2023-03-25
  • experimental-2023-03-25-base
  • experimental-2023-03-26
  • experimental-2023-03-26-base
  • experimental-2023-03-30
  • experimental-2023-03-30-base
  • experimental-2023-03-31
  • experimental-2023-03-31-base
  • experimental-2023-04-01
  • experimental-2023-04-01-base
  • experimental-2023-04-08
  • experimental-2023-04-08-base
  • experimental-2023-04-10
  • experimental-2023-04-10-base
  • experimental-2023-04-13
  • experimental-2023-04-13-base
  • experimental-2023-04-15
  • experimental-2023-04-15-base
  • experimental-2023-04-16
  • experimental-2023-04-16-base
  • experimental-2023-04-18
  • experimental-2023-04-18-base
  • experimental-2023-04-20
  • experimental-2023-04-20-base
  • experimental-2023-04-26
  • experimental-2023-04-26-base
  • experimental-2023-04-28
  • experimental-2023-04-28-base
  • experimental-2023-04-30
  • experimental-2023-04-30-base
  • experimental-2023-05-02
  • experimental-2023-05-02-base
  • experimental-2023-05-03
  • experimental-2023-05-03-base
  • experimental-2023-05-12
  • experimental-2023-05-12-base
  • experimental-2023-05-21
  • experimental-2023-05-21-base
  • experimental-2023-05-25
  • experimental-2023-05-25-base
  • experimental-2023-07-02
  • experimental-2023-07-02-base
  • experimental-2023-07-04
  • experimental-2023-07-04-base
  • experimental-2023-07-12
  • experimental-2023-07-12-base
  • experimental-2023-07-16
  • experimental-2023-07-16-base
  • experimental-2023-08-04
  • experimental-2023-08-04-base
  • experimental-2023-08-10
  • experimental-2023-08-10-base
  • experimental-2023-09-08
  • experimental-2023-09-08-base
  • experimental-2023-09-09
  • experimental-2023-09-09-base
  • experimental-2023-09-10
  • experimental-2023-09-10-base
  • experimental-2023-09-11
  • experimental-2023-09-11-base
  • experimental-2023-09-12
  • experimental-2023-09-12-base
  • experimental-2023-09-13
  • experimental-2023-09-13-base
  • experimental-2023-09-15
  • experimental-2023-09-15-base
  • experimental-2023-09-16
  • experimental-2023-09-16-base
  • experimental-2023-09-18
  • experimental-2023-09-18-base
  • experimental-2023-09-20
  • experimental-2023-09-20-base
  • experimental-2023-09-27
  • experimental-2023-09-27-base
  • experimental-2023-09-28
  • experimental-2023-09-28-base
  • experimental-2023-09-29
  • experimental-2023-09-29-base
  • experimental-2023-10-02
  • experimental-2023-10-02-base
  • experimental-2023-10-13
  • experimental-2023-10-13-base
  • experimental-2023-10-14
  • experimental-2023-10-14-base
  • experimental-2023-10-16
  • experimental-2023-10-16-base
  • experimental-2023-10-23
  • experimental-2023-10-23-base
137 results

Target

Select target project
No results found
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • 2014.3.x
  • 2014.4.x
  • babel
  • experimental
  • hoodselector
  • master
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • radv-filterd
  • v2015.1.x
  • v2016.1.x
  • v2016.2.4-batmanbug
  • v2016.2.x
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2018.2.x
  • v2019.1-ffs
  • v2019.1.1-ffs
  • v2019.1.2-ffs
  • v2020.1-ffs
  • v2020.1.1-ffs
  • v2020.1.3-ffs
  • v2020.2-ffs
  • v2020.2.1-ffs
  • v2020.2.2-ffs
  • v2020.2.3-ffs
  • v2020.2.x
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • v2014.1
  • v2014.2
  • v2014.3
  • v2014.3.1
  • v2014.4
  • v2015.1
  • v2015.1.1
  • v2015.1.2
  • v2016.1
  • v2016.1.1
  • v2016.1.2
  • v2016.1.3
  • v2016.1.4
  • v2016.1.5
  • v2016.1.6
  • v2016.2
  • v2016.2.1
  • v2016.2.2
  • v2016.2.3
  • v2016.2.4
  • v2016.2.5
  • v2016.2.6
  • v2016.2.7
  • v2017.1
  • v2017.1.1
  • v2017.1.2
  • v2017.1.3
  • v2017.1.4
  • v2017.1.5
  • v2017.1.6
  • v2017.1.7
  • v2017.1.8
  • v2018.1
  • v2018.1.1
  • v2018.1.2
  • v2018.1.3
  • v2018.1.4
  • v2018.2
  • v2018.2-ffs0.1
  • v2018.2.1
  • v2018.2.1-ffs0.1
  • v2018.2.2-ffs0.1
  • v2018.2.3-ffs0.1
  • v2019.1-ffs0.1
  • v2019.1.1-ffs0.1
  • v2019.1.2-ffs0.1
  • v2020.1-ffs0.1
  • v2020.1.1-ffs0.1
  • v2020.1.3-ffs0.1
  • v2020.2
  • v2020.2-ffs0.1
  • v2020.2.1-ffs0.1
  • v2020.2.2-ffs0.1
  • v2020.2.3-ffs0.1
  • v2020.2.3-ffs0.2
  • v2020.2.3-ffs0.3
  • v2020.2.x-ffs0.1
  • v2021.1-ffs0.1
  • v2021.1.1-ffs0.1
  • v2021.1.1-ffs0.2
  • v2021.1.1-ffs0.3
  • v2021.1.1-ffs0.4
  • v2021.1.2-ffs0.1
  • v2021.1.2-ffs0.2
98 results
Show changes

Commits on Source 2078

1,978 additional commits have been omitted to prevent performance issues.
627 files
+ 18065
11124
Compare changes
  • Side-by-side
  • Inline

Files

.ecrc

0 → 100644
+3 −0
Original line number Diff line number Diff line
{
  "Exclude": ["docs/_build"]
}
+55 −0
Original line number Diff line number Diff line
@@ -7,6 +7,61 @@ insert_final_newline = true
indent_style = tab
charset = utf-8

[Dockerfile]
indent_style = space
indent_size = 4

[/patches/**]
indent_style = unset
indent_size = unset

[*.c]

[*.css]

[*.dia]
indent_style = space
indent_size = 2

[*.h]

[*.html]

[*.js]

[*{.json,.ecrc}]
indent_style = space
indent_size = 2

[*.lua]

[{Makefile,*.mk}]
indent_style = unset

[*.md]
indent_style = space
indent_size = 4

[*.pl]

[*.py]
indent_style = space
indent_size = 4

[*.rst]
indent_style = space
indent_size = 2

[*.sh]

[*.yml]
indent_style = space
indent_size = 2

[CMakeLists.txt]
indent_style = space
indent_size = 2

[{docs,contrib/ci}/*site*/**/*.conf]
indent_style = space
indent_size = 2
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ label: bug

<!--

Please carefully fill out the questionaire below to help improve the
Please carefully fill out the questionnaire below to help improve the
timely triaging of issues. Walk through the questions below and use
them as an inspiration for what information you can provide.

.github/dependabot.yml

0 → 100644
+12 −0
Original line number Diff line number Diff line
# Docs: <https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/customizing-dependency-updates>

version: 2

updates:
  - package-ecosystem: github-actions
    directory: /
    schedule: {interval: monthly}

  - package-ecosystem: pip
    directory: /docs/
    schedule: {interval: monthly}

.github/filters.yml

0 → 100644
+345 −0
Original line number Diff line number Diff line
{
  "armsr-armv7": [
    "targets/armsr-armv7",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/armsr.inc"
  ],
  "armsr-armv8": [
    "targets/armsr-armv8",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/armsr.inc"
  ],
  "ath79-generic": [
    "targets/ath79-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ath79-nand": [
    "targets/ath79-nand",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ath79-mikrotik": [
    "targets/ath79-mikrotik",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/mikrotik.inc"
  ],
  "bcm27xx-bcm2708": [
    "targets/bcm27xx-bcm2708",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/bcm27xx.inc"
  ],
  "bcm27xx-bcm2709": [
    "targets/bcm27xx-bcm2709",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/bcm27xx.inc"
  ],
  "ipq40xx-generic": [
    "targets/ipq40xx-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ipq40xx-mikrotik": [
    "targets/ipq40xx-mikrotik",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/mikrotik.inc"
  ],
  "ipq806x-generic": [
    "targets/ipq806x-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "lantiq-xrx200": [
    "targets/lantiq-xrx200",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "lantiq-xrx200_legacy": [
    "targets/lantiq-xrx200_legacy",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "lantiq-xway": [
    "targets/lantiq-xway",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mediatek-filogic": [
    "targets/mediatek-filogic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mediatek-mt7622": [
    "targets/mediatek-mt7622",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mvebu-cortexa53": [
    "targets/mvebu-cortexa53",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mpc85xx-p1010": [
    "targets/mpc85xx-p1010",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mpc85xx-p1020": [
    "targets/mpc85xx-p1020",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "qualcommax-ipq807x": [
    "targets/qualcommax-ipq807x",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ramips-mt7620": [
    "targets/ramips-mt7620",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ramips-mt7621": [
    "targets/ramips-mt7621",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ramips-mt76x8": [
    "targets/ramips-mt76x8",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "rockchip-armv8": [
    "targets/rockchip-armv8",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "sunxi-cortexa7": [
    "targets/sunxi-cortexa7",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "x86-generic": [
    "targets/x86-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/x86.inc"
  ],
  "x86-geode": [
    "targets/x86-geode",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "x86-legacy": [
    "targets/x86-legacy",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/x86.inc"
  ],
  "x86-64": [
    "targets/x86-64",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/x86.inc",
    "contrib/ci/minimal-site/**",
    "package/**"
  ],
  "bcm27xx-bcm2710": [
    "targets/bcm27xx-bcm2710",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/bcm27xx.inc"
  ],
  "bcm27xx-bcm2711": [
    "targets/bcm27xx-bcm2711",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/bcm27xx.inc"
  ],
  "ipq40xx-chromium": [
    "targets/ipq40xx-chromium",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "kirkwood-generic": [
    "targets/kirkwood-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mvebu-cortexa9": [
    "targets/mvebu-cortexa9",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ]
}

.github/labeler.yml

0 → 100644
+89 −0
Original line number Diff line number Diff line
---
"3. topic: batman-adv":
  - changed-files:
    - any-glob-to-any-file:
      - docs/package/gluon-mesh-batman-adv*
      - package/gluon-alfred/**
      - package/gluon-client-bridge/**
      - package/gluon-mesh-batman-adv/**
      - package/libbatadv/**
"3. topic: build":
  - changed-files:
    - any-glob-to-any-file:
      - Makefile
      - scripts/**
"3. topic: config-mode":
  - changed-files:
    - any-glob-to-any-file:
      - docs/dev/web/config-mode.rst
      - docs/package/gluon-config-mode-*
      - package/gluon-config-mode-*/**
      - package/gluon-web*/**
"3. topic: continuous integration":
  - changed-files:
    - any-glob-to-any-file:
      - .github/workflows/*
      - contrib/actions/**
      - contrib/ci/**
"3. topic: docs":
  - changed-files:
    - any-glob-to-any-file:
      - docs/**
"3. topic: fastd":
  - changed-files:
    - any-glob-to-any-file:
      - docs/features/fastd*
      - package/gluon-mesh-vpn-fastd/**
"3. topic: firewall":
  - changed-files:
    - any-glob-to-any-file:
      - package/**/*-firewall
      - package/gluon-ebtables-*/**
"3. topic: hardware":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-core/luasrc/lib/gluon/upgrade/010-primary-mac
      - package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua
      - targets/*
"3. topic: multidomain":
  - changed-files:
    - any-glob-to-any-file:
      - docs/features/multidomain*
      - docs/multidomain-site-example/**
      - package/gluon-config-mode-domain-select/**
      - package/gluon-scheduled-domain-switch/**
"3. topic: olsr":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-l3roamd/**
      - package/gluon-mesh-olsrd/**
      - package/gluon-mmfd/**
"3. topic: package":
  - changed-files:
    - any-glob-to-any-file:
      - package/**
"3. topic: respondd":
  - changed-files:
    - any-glob-to-any-file:
      - package/**/*respondd*
      - package/gluon-respondd/**
"3. topic: status-page":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-status-page/**
"3. topic: tests":
  - changed-files:
    - any-glob-to-any-file:
      - tests/**
"3. topic: wireguard":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-mesh-vpn-wireguard/**
"3. topic: wireless":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-mesh-wireless-sae/**
      - package/gluon-private-wifi/**
      - package/gluon-web-private-wifi/**
      - package/gluon-web-wifi-config/**
      - package/gluon-wireless-encryption-wpa3/**
+20 −0
Original line number Diff line number Diff line
name: Backport
on:
  pull_request_target:
    types: [closed, labeled]
permissions:
  contents: write # so it can comment
  pull-requests: write # so it can create pull requests
jobs:
  backport:
    name: Backport Pull Request
    if: github.repository_owner == 'freifunk-gluon' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Create backport PRs
        uses: korthout/backport-action@v3.3.0
        with:
          # Config README: https://github.com/korthout/backport-action#backport-action
          pull_description: |-
            Automatic backport to `${target_branch}`, triggered by a label in #${pull_number}.
+48 −0
Original line number Diff line number Diff line
# Based on the example from https://docs.github.com/en/actions/publishing-packages/publishing-docker-images
name: Create and publish a Docker image

on:
  push:
    branches:
      - 'main'
      - 'next'
      - 'v202[0-9].[0-9].x'
    tags:
      - 'v*'
  pull_request:

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}-build

jobs:
  build-and-push-image:
    runs-on: ubuntu-22.04
    permissions: write-all
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Log in to the Container registry
        uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1
        if: ${{ github.repository_owner == 'freifunk-gluon' && github.event_name == 'push' }}
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      - name: Build and push Docker image
        uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
        with:
          context: ./contrib/docker
          push: ${{ github.repository_owner == 'freifunk-gluon' && github.event_name == 'push' }}
          platforms: linux/amd64,linux/arm64
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
Original line number Diff line number Diff line
name: Build Documentation
on:
  push:
    paths:
      - 'docs/**'
      - '.github/workflows/build-docs.yml'
  pull_request:
    types: [opened, synchronize, reopened]
    paths:
      - 'docs**/'
      - '.github/workflows/build-docs.yml'
permissions:
  contents: read

jobs:
  build-documentation:
    name: docs
    runs-on: ubuntu-latest
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v1
      - uses: actions/checkout@v5
      - name: Install Dependencies
        run: sudo pip3 install sphinx-rtd-theme
        run: sudo pip3 install -r docs/requirements.txt
      - name: Build documentation
        run: make -C docs html
      - name: Archive build output
        uses: actions/upload-artifact@v1
        uses: actions/upload-artifact@v4
        with:
          name: docs_output
          path: docs/_build/html
+51 −0
Original line number Diff line number Diff line
---
name: "Update OpenWrt base"

on:
  workflow_dispatch:
    inputs:
      branch:
        description: "Branch to create update for"
        required: true
        default: "main"

jobs:
  update-openwrt:
    runs-on: ubuntu-22.04
    env:
      COMMIT_NAME: Gluon CI Bot
      COMMIT_EMAIL: bot@freifunk-gluon.github.io
    steps:
      - name: Clone Gluon
        uses: actions/checkout@v5
        with:
          ref: ${{ github.event.inputs.branch }}
      
      - name: Configure Git User and E-Mail
        run: git config --global user.name "${{ env.COMMIT_NAME }}" && git config --global user.email "${{ env.COMMIT_EMAIL }}"
      
      - name: Get update branch name
        id: branch-name
        run: echo "branch-name=update-openwrt-${{ github.event.inputs.branch }}-$(date +%s)" >> $GITHUB_OUTPUT

      - name: Link example Site
        run: ln -s docs/site-example site
      
      - name: Invoke update-modules
        run: make update-modules
      
      - name: Refresh patches
        run: make refresh-patches
      
      - name: Check if unstaged commits exist
        run: git diff --exit-code || echo "::warning::Patches need a manual refresh"
      
      - name: Checkout individual branch name
        run: git checkout -b ${{ steps.branch-name.outputs.branch-name }}
      
      - name: Push branch
        run: git push origin HEAD

      - name: Emit PR creation message
        run:
          echo "::notice::Create pull-request at https://github.com/${{ github.repository }}/compare/${{ github.event.inputs.branch }}...${{ steps.branch-name.outputs.branch-name }}?quick_pull=1"
+22 −0
Original line number Diff line number Diff line
name: Check generated CI
on:
  push:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  contents: read

jobs:
  check-ci:
    name: Check generated CI
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Install example site
        run: ln -s ./docs/site-example ./site
      - name: Update CI
        run: make update-ci
      - name: Show diff
        run: git status; git diff
      - name: Patch status
        run: git diff-files --quiet
+30 −0
Original line number Diff line number Diff line
---
name: Check patches
on:
  push:
    paths:
      - 'modules'
      - 'patches/**'
      - '.github/workflows/check-patches.yml'
  pull_request:
    types: [opened, synchronize, reopened]
    paths:
      - 'modules'
      - 'patches/**'
      - '.github/workflows/check-patches.yml'
permissions:
  contents: read

jobs:
  check-patches:
    name: Check patches
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Refresh patches
        run: make refresh-patches GLUON_SITEDIR="contrib/ci/minimal-site"
      - name: Show diff
        run: git status; git diff
      - name: Patch status
        run: git diff-files --quiet
+21 −0
Original line number Diff line number Diff line
name: "Label PRs"

on:
  # only execute base branch actions
  pull_request_target:

permissions:
  contents: read

jobs:
  labels:
    permissions:
      contents: read  # for actions/labeler to determine modified files
      pull-requests: write  # for actions/labeler to add labels to PRs
    runs-on: ubuntu-22.04
    if: github.repository_owner == 'freifunk-gluon'
    steps:
    - uses: actions/labeler@v5
      with:
        repo-token: ${{ secrets.GITHUB_TOKEN }}
        sync-labels: true
+54 −0
Original line number Diff line number Diff line
name: Lint
on:
  push:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  contents: read

jobs:
  lua:
    name: Lua
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Install Dependencies
        run: sudo apt-get -y update && sudo apt-get -y install lua-check
      - name: Install example site
        run: ln -s ./docs/site-example ./site
      - name: Lint Lua code
        run: make lint-lua

  sh:
    name: Shell
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Install Dependencies
        run: sudo apt-get -y update && sudo apt-get -y install shellcheck
      - name: Install example site
        run: ln -s ./docs/site-example ./site
      - name: Lint shell code
        run: make lint-sh

  editorconfig:
    name: Editorconfig
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Install Dependencies
        run: sudo apt install curl tar
      - name: Install editorconfig-checker
        env:
          VERSION: 2.7.0
          OS: linux
          ARCH: amd64
        run: |
          curl -O -L -C - https://github.com/editorconfig-checker/editorconfig-checker/releases/download/$VERSION/ec-$OS-$ARCH.tar.gz
          tar xzf ec-$OS-$ARCH.tar.gz
          sudo mv ./bin/ec-$OS-$ARCH /usr/bin/editorconfig-checker
          sudo chmod +x /usr/bin/editorconfig-checker
      - name: Install example site
        run: ln -s ./docs/site-example ./site
      - name: Lint editorconfig
        run: make lint-editorconfig
+1 −0
Original line number Diff line number Diff line
@@ -7,3 +7,4 @@
.bash_history
.subversion
.wget-hsts
/.scmversion
+5 −0
Original line number Diff line number Diff line
@@ -25,9 +25,11 @@ files["package/**/check_site.lua"] = {
		"extend",
		"in_domain",
		"in_site",
		"value",
		"need",
		"need_alphanumeric_key",
		"need_array",
		"need_array_elements_exclusive",
		"need_array_of",
		"need_boolean",
		"need_chanlist",
@@ -49,6 +51,7 @@ files["package/**/check_site.lua"] = {

files["package/**/luasrc/lib/gluon/config-mode/*"] = {
	globals = {
		"MultiListValue",
		"DynamicList",
		"Flag",
		"Form",
@@ -62,6 +65,7 @@ files["package/**/luasrc/lib/gluon/config-mode/*"] = {
		"translate",
		"translatef",
		"Value",
		"Element",
	},
}

@@ -110,5 +114,6 @@ files["package/features"] = {
	read_globals = {
		"_",
		"feature",
		"when",
	},
}

.readthedocs.yaml

0 → 100644
+20 −0
Original line number Diff line number Diff line
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Build documentation in the docs/ directory with Sphinx
sphinx:
  configuration: docs/conf.py

# Optionally set the version of Python and requirements required to build your docs
python:
   install:
   - requirements: docs/requirements.txt

build:
    os: ubuntu-22.04
    tools:
        python: "3.11"
+7 −7
Original line number Diff line number Diff line
@@ -23,19 +23,19 @@ using other parts or why the proposed change breaks other parts of the system.
They might even refuse the idea altogether - after all, they have to sleep well
after merging the changes, too.

The preferred way to discuss in the IRC channel ([#gluon] on irc.hackint.org)
or on the [mailing list], however, you can also open a new issue on Github to
The preferred way to discuss is in the IRC channel ([#gluon] on irc.hackint.org)
or on the [mailing list], however, you can also open a new issue on GitHub to
discuss there. We maintain a [list of rejected features] and we'd like to
kindly ask you to review it first. In general, looking for duplicates may save
you some time.

Develop on top of master
------------------------
Develop on top of main
----------------------
If you are not developing something specific to a release (like for example a
security fix to a feature that got completely rewritten since the release),
develop it on top of the master branch. New features and even feature changes
develop it on top of the main branch. New features and even feature changes
aren't usually backported to old releases, but will be included in the upcoming
release, which will be built from master.
release, which will be built from main.

Use descriptive commit messages
-------------------------------
@@ -48,6 +48,6 @@ existing commit messages to get the idea.


[packages]: https://gluon.readthedocs.io/en/latest/user/site.html#packages
[#gluon]: https://webirc.hackint.org/#gluon
[#gluon]: https://chat.hackint.org/?join=gluon
[mailing list]: mailto:gluon@luebeck.freifunk.net
[list of rejected features]: https://github.com/freifunk-gluon/gluon/issues?q=label%3A%222.+status%3A+rejected%22
+3 −1
Original line number Diff line number Diff line
BSD 2-Clause License

The code of Project Gluon may be distributed under the following terms, unless
noted otherwise in individual files or subtrees.

Copyright (c) 2013-2018, Project Gluon
Copyright (c) Project Gluon
All rights reserved.

Redistribution and use in source and binary forms, with or without
+59 −21
Original line number Diff line number Diff line
@@ -19,14 +19,31 @@ escape = '$(subst ','\'',$(1))'
GLUON_SITEDIR ?= site
$(eval $(call mkabspath,GLUON_SITEDIR))

$(GLUON_SITEDIR)/site.mk:
ifeq ($(realpath $(GLUON_SITEDIR)/site.mk),)
$(error No site configuration was found. Please check out a site configuration to $(GLUON_SITEDIR))
endif

include $(GLUON_SITEDIR)/site.mk

GLUON_RELEASE ?= $(error GLUON_RELEASE not set. GLUON_RELEASE can be set in site.mk or on the command line)

GLUON_DEPRECATED ?= $(error GLUON_DEPRECATED not set. Please consult the documentation)
GLUON_DEPRECATED ?= 0

ifneq ($(GLUON_BRANCH),)
  $(warning *** Warning: GLUON_BRANCH has been deprecated, please set GLUON_AUTOUPDATER_BRANCH and GLUON_AUTOUPDATER_ENABLED instead.)
  GLUON_AUTOUPDATER_BRANCH ?= $(GLUON_BRANCH)
  GLUON_AUTOUPDATER_ENABLED ?= 1
endif

ifneq ($(GLUON_FEATURES)$(GLUON_FEATURES_standard)$(GLUON_FEATURES_tiny),)
  $(error GLUON_FEATURES is obsolete, please use the image-customization.lua file instead)
endif

ifneq ($(GLUON_SITE_PACKAGES)$(GLUON_SITE_PACKAGES_standard)$(GLUON_SITE_PACKAGES_tiny),)
  $(error GLUON_SITE_PACKAGES is obsolete, please use the image-customization.lua file instead)
endif

GLUON_AUTOUPDATER_ENABLED ?= 0

# initialize (possibly already user set) directory variables
GLUON_TMPDIR ?= tmp
@@ -34,6 +51,7 @@ GLUON_OUTPUTDIR ?= output
GLUON_IMAGEDIR ?= $(GLUON_OUTPUTDIR)/images
GLUON_PACKAGEDIR ?= $(GLUON_OUTPUTDIR)/packages
GLUON_DEBUGDIR ?= $(GLUON_OUTPUTDIR)/debug
GLUON_METADIR ?= $(GLUON_OUTPUTDIR)/meta
GLUON_TARGETSDIR ?= targets
GLUON_PATCHESDIR ?= patches

@@ -44,9 +62,14 @@ $(eval $(call mkabspath,GLUON_PACKAGEDIR))
$(eval $(call mkabspath,GLUON_TARGETSDIR))
$(eval $(call mkabspath,GLUON_PATCHESDIR))

GLUON_VERSION := $(shell scripts/getversion.sh '.')

# Set default SITE_VERSION if not set by user
GLUON_SITE_VERSION ?= $(shell scripts/getversion.sh '$(GLUON_SITEDIR)')

GLUON_MULTIDOMAIN ?= 0
GLUON_AUTOREMOVE ?= 0
GLUON_DEBUG ?= 0
GLUON_DEBUG ?= 1
GLUON_MINIFY ?= 1

# Can be overridden via environment/command line/... to use the Gluon
@@ -56,9 +79,10 @@ src-link gluon_base ../../package
endef

GLUON_VARS = \
	GLUON_VERSION GLUON_SITE_VERSION \
	GLUON_RELEASE GLUON_REGION GLUON_MULTIDOMAIN GLUON_AUTOREMOVE GLUON_DEBUG GLUON_MINIFY GLUON_DEPRECATED \
	GLUON_DEVICES GLUON_TARGETSDIR GLUON_PATCHESDIR GLUON_TMPDIR GLUON_IMAGEDIR GLUON_PACKAGEDIR GLUON_DEBUGDIR \
	GLUON_SITEDIR GLUON_RELEASE GLUON_BRANCH GLUON_LANGS GLUON_BASE_FEEDS \
	GLUON_METADIR GLUON_SITEDIR GLUON_AUTOUPDATER_BRANCH GLUON_AUTOUPDATER_ENABLED GLUON_LANGS GLUON_BASE_FEEDS \
	GLUON_TARGET BOARD SUBTARGET

unexport $(GLUON_VARS)
@@ -82,9 +106,21 @@ update-patches: FORCE
	scripts/update-patches.sh
	scripts/patch.sh

refresh-patches: FORCE
	@
	export $(GLUON_ENV)
	scripts/update.sh
	scripts/patch.sh
	scripts/update-patches.sh

update-feeds: FORCE
	@$(GLUON_ENV) scripts/feeds.sh

update-modules: FORCE
	@scripts/update-modules.sh

update-ci: FORCE
	@$(GLUON_ENV) scripts/update-ci.sh

GLUON_TARGETS :=

@@ -114,13 +150,6 @@ define CheckTarget
	fi
endef

define CheckExternal
	if [ ! -d openwrt ]; then
		echo "You don't seem to have obtained the external repositories needed by Gluon; please call \`make update\` first!"
		exit 1
	fi
endef

define CheckSite
	if ! GLUON_SITEDIR='$(GLUON_SITEDIR)' GLUON_SITE_CONFIG='$(1).conf' $(LUA) -e 'assert(dofile("scripts/site_config.lua")(os.getenv("GLUON_SITE_CONFIG")))'; then
		echo 'Your site configuration ($(1).conf) did not pass validation'
@@ -133,7 +162,10 @@ list-targets: FORCE
		echo "$$target"
	done

lint: lint-lua lint-sh
lint: lint-editorconfig lint-lua lint-sh

lint-editorconfig: FORCE
	@scripts/lint-editorconfig.sh

lint-lua: FORCE
	@scripts/lint-lua.sh
@@ -147,9 +179,10 @@ LUA := openwrt/staging_dir/hostpkg/bin/lua
$(LUA):
	+@

	$(CheckExternal)
	scripts/module_check.sh

	[ -e openwrt/.config ] || $(OPENWRTMAKE) defconfig
	$(GLUON_ENV) scripts/basic_openwrt_config.sh > openwrt/.config
	$(OPENWRTMAKE) defconfig
	$(OPENWRTMAKE) tools/install
	$(OPENWRTMAKE) package/lua/host/compile

@@ -157,17 +190,22 @@ $(LUA):
config: $(LUA) FORCE
	+@

	$(CheckExternal)
	scripts/module_check.sh
	$(CheckTarget)
	$(foreach conf,site $(patsubst $(GLUON_SITEDIR)/%.conf,%,$(wildcard $(GLUON_SITEDIR)/domains/*.conf)),\
		$(call CheckSite,$(conf)); \
	)

	$(OPENWRTMAKE) prepare-tmpinfo
	$(GLUON_ENV) $(LUA) scripts/target_config.lua > openwrt/.config
	$(OPENWRTMAKE) defconfig
	$(GLUON_ENV) $(LUA) scripts/target_config_check.lua


container: FORCE
	@scripts/container.sh


all: config
	+@
	$(GLUON_ENV) $(LUA) scripts/clean_output.lua
@@ -185,23 +223,23 @@ dirclean: FORCE

manifest: $(LUA) FORCE
	@
	[ '$(GLUON_BRANCH)' ] || (echo 'Please set GLUON_BRANCH to create a manifest.'; false)
	[ '$(GLUON_AUTOUPDATER_BRANCH)' ] || (echo 'Please set GLUON_AUTOUPDATER_BRANCH to create a manifest.'; false)
	echo '$(GLUON_PRIORITY)' | grep -qE '^([0-9]*\.)?[0-9]+$$' || (echo 'Please specify a numeric value for GLUON_PRIORITY to create a manifest.'; false)
	$(CheckExternal)
	scripts/module_check.sh

	(
		export $(GLUON_ENV)
		echo 'BRANCH=$(GLUON_BRANCH)'
		echo 'BRANCH=$(GLUON_AUTOUPDATER_BRANCH)'
		echo "DATE=$$($(LUA) scripts/rfc3339date.lua)"
		echo 'PRIORITY=$(GLUON_PRIORITY)'
		echo
		for target in $(GLUON_TARGETS); do
			$(LUA) scripts/generate_manifest.lua "$$target"
		done
	) > 'tmp/$(GLUON_BRANCH).manifest.tmp'
	) > 'tmp/$(GLUON_AUTOUPDATER_BRANCH).manifest.tmp'

	mkdir -p '$(GLUON_IMAGEDIR)/sysupgrade'
	mv 'tmp/$(GLUON_BRANCH).manifest.tmp' '$(GLUON_IMAGEDIR)/sysupgrade/$(GLUON_BRANCH).manifest'
	mv 'tmp/$(GLUON_AUTOUPDATER_BRANCH).manifest.tmp' '$(GLUON_IMAGEDIR)/sysupgrade/$(GLUON_AUTOUPDATER_BRANCH).manifest'

FORCE: ;

+45 −7
Original line number Diff line number Diff line
Documentation (incomplete at this time, contribute if you can!) may be found at
https://gluon.readthedocs.io/.
[![Build Gluon](https://github.com/freifunk-gluon/gluon/actions/workflows/build-gluon.yml/badge.svg?branch=main)](https://github.com/freifunk-gluon/gluon/actions/workflows/build-gluon.yml)
[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://opensource.org/license/bsd-2-clause/)
[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/freifunk-gluon/gluon?sort=semver)](https://github.com/freifunk-gluon/gluon/releases/latest)

# Gluon

Gluon is a firmware framework to build preconfigured OpenWrt images for public mesh networks.

## Overview

Gluon provides an easy-to-use firmware for a public, decentral WLAN and/or wire based mesh network.
Common network capable devices, like smartphones, laptops or desktop PCs can connect to the mesh network and communicate over it, without the need of passwords for access and without the need of installing special software.
Additionally, internet access and merging mesh clouds can be accomplished over a WAN through VPN connected gateways.

Gluon's features include:

* a decentral mesh network
* easy configuration mode for less techy users
* community-specific technical settings and customizations through a common site.conf and site.mk
* ecdsa signature-based autoupdater
* node status web page
* publication of node information + statistics through respondd
* a variety of preconfigured mesh and VPN protocols:


Supported mesh protocols:

* batman-adv (BATMAN IV fully, BATMAN V partially)
* OLSRv2 (partially)


Supported protocols for node-to-node connections:

* WLAN: 802.11s (with forwarding disabled)
* WAN: VPNs via fastd and Wireguard
* LAN: via VXLAN

## Getting started

We have a huge amount of documentation over at https://gluon.readthedocs.io/.

If you're new to Gluon and ready to get your feet wet, have a look at the
[Getting Started Guide](https://gluon.readthedocs.io/en/latest/user/getting_started.html).

Gluon's developers frequent an IRC chatroom at [#gluon](ircs://irc.hackint.org/#gluon)
on [hackint](https://hackint.org/). There is also a [webchat](https://webirc.hackint.org/#irc://irc.hackint.org/#gluon)
that allows for access from within your browser.
on [hackint](https://hackint.org/). There is also a [webchat](https://chat.hackint.org/?join=gluon)
that allows for uncomplicated access from within your browser. This channel is also available as a bridged Matrix Room at [#gluon:hackint.org](https://matrix.to/#/#gluon:hackint.org).

## Issues & Feature requests

@@ -19,12 +57,12 @@ the future development of Gluon.

## Use a release!

Please refrain from using the `master` branch for anything else but development purposes!
Please refrain from using the `main` branch for anything else but development purposes!
Use the most recent release instead. You can list all releases by running `git tag`
and switch to one by running `git checkout v2020.2 && make update`.
and switch to one by running `git checkout v2023.2.5 && make update`.

If you're using the autoupdater, do not autoupdate nodes with anything but releases.
If you upgrade using random master commits the nodes *will break* eventually.
If you upgrade using random main commits the nodes *might break* eventually.

## Mailinglist

contrib/Dockerfile

deleted100644 → 0
+0 −27
Original line number Diff line number Diff line
FROM debian:buster-slim

RUN apt update && apt install -y --no-install-recommends \
    ca-certificates \
    file \
    git \
    subversion \
    python \
    build-essential \
    gawk \
    unzip \
    libncurses5-dev \
    zlib1g-dev \
    libssl-dev \
    libelf-dev \
    wget \
    time \
    ecdsautils \
    lua-check \
    shellcheck \
  && rm -rf /var/lib/apt/lists/*

RUN useradd -d /gluon gluon
USER gluon

VOLUME /gluon
WORKDIR /gluon
+23 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash

# For a List of pre-installed packages on the runner image see
# https://github.com/actions/runner-images/tree/main?tab=readme-ov-file#available-images

echo "Disk space before cleanup"
df -h

# Remove packages not required to run the Gluon build CI
sudo apt-get -y remove \
	dotnet-* \
	firefox \
	google-chrome-stable \
	kubectl \
	microsoft-edge-stable \
	temurin-*-jdk

# Remove Android SDK tools
sudo rm -rf /usr/local/lib/android

echo "Disk space after cleanup"
df -h
+0 −60
Original line number Diff line number Diff line
#!/usr/bin/env python3

import sys

ACTIONS_HEAD = """
# Update this file after adding/removing/renaming a target by running
# `make list-targets BROKEN=1 | ./contrib/actions/generate-actions.py > ./.github/workflows/build-gluon.yml`

name: Build Gluon
on:
  push:
    branches:
      - master
      - next
      - v20*
  pull_request:
    types: [opened, synchronize, reopened]
jobs:
"""

ACTIONS_TARGET="""
  {target_name}:
    name: {target_name}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: actions/cache@v2
        id: cache-dl
        with:
          path: dl_target
          key: openwrt-dl-{target_name}-${{{{ hashFiles('modules') }}}}
      - name: Prepare download cache
        if: steps.cache-dl.outputs.cache-hit == 'true'
        run: mkdir -p openwrt/dl; mv dl_target/* openwrt/dl/; ls openwrt/dl
      - name: Install Dependencies
        run: sudo contrib/actions/install-dependencies.sh
      - name: Build
        run: contrib/actions/run-build.sh {target_name}
      - name: Create cache to save
        if: steps.cache-dl.outputs.cache-hit != 'true'
        run: mkdir dl_target; mv openwrt/dl/* dl_target/; find dl_target/ -size +20M -delete
      - name: Archive build logs
        if: ${{{{ !cancelled() }}}}
        uses: actions/upload-artifact@v1
        with:
          name: {target_name}_logs
          path: openwrt/logs
      - name: Archive build output
        uses: actions/upload-artifact@v1
        with:
          name: {target_name}_output
          path: output
"""

output = ACTIONS_HEAD

for target in sys.stdin:
	output += ACTIONS_TARGET.format(target_name=target.strip())

print(output)
Original line number Diff line number Diff line
#!/usr/bin/env python3

# Update target filters using
#   make update-ci

import re
import os
import sys
import json

# these changes trigger rebuilds on all targets
common = [
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
]

# these changes are only built on x86-64
extra = [
    "contrib/ci/minimal-site/**",
    "package/**"
]

_filter = dict()

# INCLUDE_PATTERN matches:
# include '...'
# include "..."
# include("...")
# include('...')
INCLUDE_PATTERN = "^\\s*include *\\(? *[\"']([^\"']+)[\"']"

# construct filters map from stdin
for target in sys.stdin:
    target = target.strip()

    _filter[target] = [
        f"targets/{target}"
    ] + common

    target_file = os.path.join(os.environ['GLUON_TARGETSDIR'], target)
    with open(target_file) as f:
        includes = re.findall(INCLUDE_PATTERN, f.read(), re.MULTILINE)
        _filter[target].extend([f"targets/{i}" for i in includes])

    if target == "x86-64":
        _filter[target].extend(extra)

# print filters to stdout in json format, because json is stdlib and yaml compatible.
print(json.dumps(_filter, indent=2))
+0 −10
Original line number Diff line number Diff line
#!/bin/sh

set -e

cp contrib/actions/sources.list /etc/apt/sources.list
rm -rf /etc/apt/sources.list.d
apt update
apt install git subversion build-essential python gawk unzip libncurses5-dev zlib1g-dev libssl-dev wget time
apt clean
rm -rf /var/lib/apt/lists/*
Original line number Diff line number Diff line
@@ -6,8 +6,12 @@ export BROKEN=1
export GLUON_AUTOREMOVE=1
export GLUON_DEPRECATED=1
export GLUON_SITEDIR="contrib/ci/minimal-site"
export GLUON_TARGET=$1
export GLUON_TARGET="$1"
export BUILD_LOG=1

BUILD_THREADS="$(($(nproc) + 1))"

echo "Building Gluon with $BUILD_THREADS threads"

make update
make -j2 V=s
make -j$BUILD_THREADS V=s
+16 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash

echo "-- CPU --"
cat /proc/cpuinfo

echo "-- Memory --"
cat /proc/meminfo

echo "-- Disk --"
df -h

echo "-- Kernel --"
uname -a

echo "-- Network --"
ip addr

contrib/actions/sources.list

deleted100644 → 0
+0 −2
Original line number Diff line number Diff line
deb http://mirror.netcologne.de/ubuntu/ bionic main restricted
deb http://mirror.netcologne.de/ubuntu/ bionic-updates main restricted
+146 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3

import argparse
import json
import sys
from enum import Enum

# Enum Class for checking image size
class ImageSizeCheck(Enum):
    OK = "OK"
    TOO_BIG = "TOO_BIG"
    IGNORED = "IGNORED"
    UNKNOWN = "UNKNOWN"


# Some devices pad their images to IMAGE_SIZE and apply a firmware header.
# Exclude this from the image size check.
excluded_devices = [
    "tplink_cpe210-v1",
    "tplink_cpe210-v2",
    "tplink_cpe210-v3",
    "tplink_cpe220-v3",
    "tplink_cpe510-v1",
    "tplink_cpe510-v2",
    "tplink_cpe510-v3",
    "tplink_cpe710-v1",
    "tplink_wbs210-v1",
    "tplink_wbs210-v2",
    "tplink_wbs510-v1"
]


def open_json(file_path):
    with open(file_path, 'r') as f:
        return json.load(f)


def load_openwrt_profile_json(json_path):
    profiles = []
    profile_json = open_json(json_path)
    for profile_name, profile_data in profile_json["profiles"].items():
        device_profile = {
            "name": profile_name,
        }
        if "image" in profile_data.get("file_size_limits", {}):
            device_profile["max_image_size"] = profile_data["file_size_limits"]["image"]

        for image in profile_data["images"]:
            if image["type"] != "sysupgrade":
                continue
            if "size" in image:
                device_profile["image_size"] = image["size"]
        
        profiles.append(device_profile)
    
    return profiles


def check_image_size_below_limit(profile, overhead=0):
    # Skip devices that pad their images
    if profile["name"] in excluded_devices:
        return ImageSizeCheck.IGNORED

    if "max_image_size" in profile and "image_size" in profile:
        if profile["image_size"] + (overhead * 1024) > profile["max_image_size"]:
            return ImageSizeCheck.TOO_BIG
        else:	
            return ImageSizeCheck.OK
    
    return ImageSizeCheck.UNKNOWN


def print_github_actions_warning(message):
    print('::warning::{}'.format(message))


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Check image size of OpenWrt profiles')
    parser.add_argument(
        'profile_json',
        help='Path to profile.json',
        nargs='+'
    )
    parser.add_argument(
        '--github-actions',
        help='Generate warnings for use with GitHub Actions',
        action='store_true'
    )
    parser.add_argument(
        '--overhead',
        type=int,
        help='Additional size to add to the image size in kilobyte',
        default=0
    )
    args = parser.parse_args()

    if args.profile_json is None:
        print('Error: profile.json not specified')
        sys.exit(1)
    
    # Load all profile.json files
    profiles = []
    for profile_file in args.profile_json:
        profiles.extend(load_openwrt_profile_json(profile_file))

    # Initialize results with all available ImageSizeCheck values
    results = {}
    for check_result in ImageSizeCheck:
        results[check_result] = []

    for profile in profiles:
        check_result = check_image_size_below_limit(profile, args.overhead)
        results[check_result].append(profile)
    
    for check_result, profiles in results.items():
        if len(profiles) == 0:
            continue

        # Group by result type for GitHub Actions
        if args.github_actions:
            print('::group::{}'.format(check_result.value))

        for profile in profiles:
            if check_result == ImageSizeCheck.TOO_BIG:
                msg = 'Image size of profile {} is too big ({} > {})'.format(
                    profile["name"],
                    profile["image_size"] + (args.overhead * 1024),
                    profile["max_image_size"])
                if args.github_actions:
                    print_github_actions_warning(msg)
                else:
                    print("Warning: {}".format(msg))
            elif check_result == ImageSizeCheck.UNKNOWN:
                msg = 'Image size of profile {} is unknown'.format(
                    profile["name"])
                print(msg)
            elif check_result == ImageSizeCheck.IGNORED:
                msg = 'Image size of profile {} is ignored (Image size {})'.format(
                    profile["name"], profile.get("image_size", "unknown"))
                print(msg)
            else:
                msg = 'Image size of profile {} is OK ({} < {})'.format(
                    profile["name"], 
                    profile["image_size"] + (args.overhead * 1024),
                    profile["max_image_size"])
                print(msg)

contrib/ci/Jenkinsfile

deleted100644 → 0
+0 −82
Original line number Diff line number Diff line
pipeline {
	agent none
	environment {
		GLUON_SITEDIR = "contrib/ci/minimal-site"
		GLUON_TARGET = "x86-64"
		BUILD_LOG = "1"
	}
	stages {
		stage('lint') {
			parallel {
				stage('lint-lua') {
					agent { label 'gluon-docker' }
					steps {
						sh label: 'Identify runner', script: 'echo $SLAVE_NAME'
						sh 'make lint-lua'
					}
				}
				stage('lint-sh') {
					agent { label 'gluon-docker-v1' }
					steps {
						sh label: 'Identify runner', script: 'echo $SLAVE_NAME'
						sh 'make lint-sh'
					}
				}
			}
		}
		stage('docs') {
			agent { label 'gluon-docker' }
			steps {
				sh label: 'Identify runner', script: 'echo $SLAVE_NAME'
				sh 'make -C docs html'
			}
		}
		stage('build') {
			agent { label 'gluon-docker-v2' }
			steps {
				sh label: 'Identify runner', script: 'echo $SLAVE_NAME'
				sh 'make update'
				sh 'test -d /dl_cache && ln -s /dl_cache openwrt/dl || true'
				timeout(time: 2, unit: "HOURS") {
					sh 'make -j$(nproc) V=s'
				}
				stash includes: '**/output/images/factory/*-x86-64.img.gz', name: 'gluon-x86-64-factory'
			}
		}
		stage('test') {
			agent { label 'gluon-vmx' }
			steps {
				sh label: 'Identify runner', script: 'echo $SLAVE_NAME'
				unstash 'gluon-x86-64-factory'
				sh label: 'Unpack image', script: 'gunzip -cd ./output/images/factory/*x86-64*.img.gz > ./image.img'
				sh label: 'Print python environment', script: 'python3 -m pip freeze'
				script {
					for (f in findFiles(glob: 'tests/*.py')) {
						timeout(time: 10, unit: "MINUTES") {
							sh label: "Test ${f.name}", script: "python3 tests/${f.name} --use-tmp-workdir"
						}
					}
				}
			}
		}
	}
}

/*
 api-history:

 Every time the build dependencies of gluon change, the version
 every container has to be rebuilt. Therefore, we use Jenkins
 labels which intoduce a version number which is documented here.
 As soon, as you properly rebuilt your docker container, you
 can notify lemoer, that you have updated your node.

 - gluon-docker-v1:
   - add shellcheck binary to the build environment
 - gluon-docker-v2:
   - add qemu-testlab testing, requires KVM virtualization support
   - require rsync dependency to be able to build the next branch
 - gluon-vmx
   - splits the qemu testing from the gluon-docker-v2 label to accomodate
     nodes without the vmx cpu flag
*/
+0 −33
Original line number Diff line number Diff line
FROM gluonmesh/build:latest

USER root

# this is needed to install default-jre-headless in debian slim images
RUN mkdir -p /usr/share/man/man1
 
RUN apt-get update && apt-get install -y default-jre-headless curl git netcat-openbsd python3 python3-pip qemu-system-x86 iproute2 openssh-client rsync
RUN python3 -m pip install jenkins-webapi sphinx sphinx_rtd_theme gluon-qemu-testlab==0.0.5
 
# Get docker-compose in the agent container
RUN mkdir -p /home/jenkins
RUN mkdir -p /var/lib/jenkins
RUN mkdir -p /remoting
RUN chown gluon /home/jenkins
RUN chown gluon /var/lib/jenkins
RUN chown gluon /remoting
 
# Start-up script to attach the slave to the master
ADD slave.py /var/lib/jenkins/slave.py

USER gluon
 
WORKDIR /home/jenkins

ENV JENKINS_URL "https://build.ffh.zone/"
ENV JENKINS_SLAVE_ADDRESS ""
ENV SLAVE_EXECUTORS "1"
ENV SLAVE_LABELS "docker"
ENV SLAVE_WORING_DIR ""
ENV CLEAN_WORKING_DIR "true"
 
CMD [ "python3", "-u", "/var/lib/jenkins/slave.py" ]
+0 −41
Original line number Diff line number Diff line
# Gluon CI using Jenkins

## Requirements
- Linux system
  - with docker installed
  - with Hardware Virtualisation (KVM Support)
    - Verify using: `lscpu | grep vmx`
    - If machine is virtualized host needs to load `kvm_intel` with `nested=1` option and cpuflags need to include `vmx`

## Architecture

![Screenshot from 2019-09-24 00-20-32](https://user-images.githubusercontent.com/601153/65468827-9edf2c80-de65-11e9-9fe0-56c3487719c3.png)

## Installation
You can support the gluon CI with your infrastructure:
1. You need to query @lemoer (freifunk@irrelefant.net) for credentials.
2. He will give you a `SLAVE_NAME` and a `SLAVE_SECRET` for your host.
3. Then go to your docker host and substitute the values for  `SLAVE_NAME` and a `SLAVE_SECRET` in the following statements:
``` shell
git clone https://github.com/freifunk-gluon/gluon/
cd gluon/contrib/ci/jenkins-community-slave/
docker build -t gluon-jenkins .
mkdir /var/cache/openwrt_dl_cache/
chown 1000:1000 /var/cache/openwrt_dl_cache
echo "z /dev/kvm 0666 - kvm -" > /etc/tmpfiles.d/kvm.conf
systemd-tmpfiles --create
docker run --detach --restart always \
    --env "SLAVE_NAME=whoareyou" \
    --env "SLAVE_SECRET=changeme" \
    --device /dev/kvm:/dev/kvm \
    --volume /var/cache/openwrt_dl_cache/:/dl_cache \
    gluon-jenkins
```
4. Check whether the instance is running correctly:
   - Your node should appear [here](https://build.ffh.zone/label/gluon-docker/).
   - When clicking on it, Jenkins should state "Agent is connected." like here: 
![Screenshot from 2019-09-24 01-00-52](https://user-images.githubusercontent.com/601153/65469209-dac6c180-de66-11e9-9d62-0d1c3b6b940b.png)
5. **Your docker container needs to be rebuilt, when the build dependencies of gluon change. As soon as build dependencies have changed, the build dependency api level has to be raised.** After you rebuilt your docker container, notifiy @lemoer, so he can bump the versioning number.

## Backoff
- If @lemoer is not reachable, please be patient at first if possible. Otherwise contact info@hannover.freifunk.net or join the channel `#freifunkh` on hackint.
+0 −103
Original line number Diff line number Diff line
from jenkins import Jenkins, JenkinsError, NodeLaunchMethod
import os
import signal
import sys
import subprocess
import shutil
import requests
import time

slave_jar = '/var/lib/jenkins/slave.jar'
slave_name = os.environ['SLAVE_NAME'] if os.environ['SLAVE_NAME'] != '' else 'docker-slave-' + os.environ['HOSTNAME']
jnlp_url = os.environ['JENKINS_URL'] + '/computer/' + slave_name + '/slave-agent.jnlp'
slave_jar_url = os.environ['JENKINS_URL'] + '/jnlpJars/slave.jar'
print(slave_jar_url)
process = None

def clean_dir(dir):
    for root, dirs, files in os.walk(dir):
        for f in files:
            os.unlink(os.path.join(root, f))
        for d in dirs:
            shutil.rmtree(os.path.join(root, d))

def slave_create(node_name, working_dir, executors, labels):
    j = Jenkins(os.environ['JENKINS_URL'], os.environ['JENKINS_USER'], os.environ['JENKINS_PASS'])
    j.node_create(node_name, working_dir, num_executors = int(executors), labels = labels, launcher = NodeLaunchMethod.JNLP)

def slave_delete(node_name):
    j = Jenkins(os.environ['JENKINS_URL'], os.environ['JENKINS_USER'], os.environ['JENKINS_PASS'])
    j.node_delete(node_name)

def slave_download(target):
    if os.path.isfile(slave_jar):
        os.remove(slave_jar)

    r = requests.get(os.environ['JENKINS_URL'] + '/jnlpJars/slave.jar')
    with open('/var/lib/jenkins/slave.jar', 'wb') as f:
        f.write(r.content)

def slave_run(slave_jar, jnlp_url):
    params = [ 'java', '-jar', slave_jar, '-jnlpUrl', jnlp_url ]
    if os.environ['JENKINS_SLAVE_ADDRESS'] != '':
        params.extend([ '-connectTo', os.environ['JENKINS_SLAVE_ADDRESS' ] ])

    if os.environ['SLAVE_SECRET'] == '':
        params.extend([ '-jnlpCredentials', os.environ['JENKINS_USER'] + ':' + os.environ['JENKINS_PASS'] ])
    else:
        params.extend([ '-secret', os.environ['SLAVE_SECRET'] ])
    return subprocess.Popen(params, stdout=subprocess.PIPE)

def signal_handler(sig, frame):
    if process != None:
        process.send_signal(signal.SIGINT)

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

def h():
    print("ERROR!: please specify environment variables")
    print("")
    print('docker run -e "SLAVE_NAME=test" -e "SLAVE_SECRET=..." jenkins')

if os.environ.get('SLAVE_NAME') is None:
    h()
    sys.exit(1)

if os.environ.get('SLAVE_SECRET') is None:
    h()
    sys.exit(1)

def master_ready(url):
    try:
        r = requests.head(url, timeout=None)
        return r.status_code == requests.codes.ok
    except:
        return False

while not master_ready(slave_jar_url):
    print("Master not ready yet, sleeping for 10sec!")
    time.sleep(10)

slave_download(slave_jar)
print('Downloaded Jenkins slave jar.')

if os.environ['SLAVE_WORING_DIR']:
    os.setcwd(os.environ['SLAVE_WORING_DIR'])

if os.environ['CLEAN_WORKING_DIR'] == 'true':
    clean_dir(os.getcwd())
    print("Cleaned up working directory.")

if os.environ['SLAVE_NAME'] == '':
    slave_create(slave_name, os.getcwd(), os.environ['SLAVE_EXECUTORS'], os.environ['SLAVE_LABELS'])
    print('Created temporary Jenkins slave.')

process = slave_run(slave_jar, jnlp_url)
print('Started Jenkins slave with name "' + slave_name + '" and labels [' + os.environ['SLAVE_LABELS'] + '].')
process.wait()

print('Jenkins slave stopped.')
if os.environ['SLAVE_NAME'] == '':
    slave_delete(slave_name)
    print('Removed temporary Jenkins slave.')
Original line number Diff line number Diff line
features {
	'autoupdater',
	'ebtables-filter-multicast',
	'ebtables-filter-ra-dhcp',
	'ebtables-limit-arp',
	'mesh-batman-adv-15',
	'mesh-vpn-fastd',
	'respondd',
	'status-page',
	'web-advanced',
	'web-wizard',
}

if not device_class('tiny') then
	features {'wireless-encryption-wpa3'}
end
Original line number Diff line number Diff line
-- This is an example site configuration for Gluon v2018.2+
-- This is an example site configuration
--
-- Take a look at the documentation located at
-- https://gluon.readthedocs.io/ for details.
@@ -10,7 +10,7 @@
  -- hostname_prefix = 'freifunk-',

  -- Name of the community.
  site_name = 'Continious Integration',
  site_name = 'Continuous Integration',

  -- Shorthand of the community.
  site_code = 'ci',
@@ -42,10 +42,14 @@
    -- Wireless channel.
    channel = 1,

    -- ESSID used for client network.
    -- ESSIDs used for client network.
    ap = {
      ssid = 'gluon-ci-ssid',
      -- disabled = true, -- (optional)

      -- Configuration for a backward compatible OWE network below.
      owe_ssid = 'owe.gluon-ci-ssid', -- (optional - SSID for OWE client network)
      owe_transition_mode = true, -- (optional - enables transition-mode - requires ssid as well as owe_ssid)
    },

    mesh = {
@@ -72,6 +76,12 @@
    },
  },

  mesh = {
    vxlan = true,
    batman_adv = {
      routing_algo = 'BATMAN_IV',
    },
  },

  -- The next node feature allows clients to always reach the node it is
  -- connected to using a known IP address.
@@ -82,16 +92,19 @@
    ip6 = 'fd::1',
  },

  mesh = {
    vxlan = true,
    batman_adv = {
      routing_algo = 'BATMAN_IV'
    }
  },
  -- Options specific to routing protocols (optional)
  -- mesh = {
    -- Options specific to the batman-adv routing protocol (optional)
    -- batman_adv = {
      -- Gateway selection class (optional)
      -- The default class 20 is based on the link quality (TQ) only,
      -- class 1 is calculated from both the TQ and the announced bandwidth
      -- gw_sel_class = 1,
    -- },
  -- },

  mesh_vpn = {
    -- enabled = true,
    mtu = 1312,

    fastd = {
      -- Refer to https://fastd.readthedocs.io/en/latest/ to better understand
@@ -99,6 +112,7 @@

      -- List of crypto-methods to use.
      methods = {'salsa2012+umac'},
      mtu = 1312,
      -- configurable = true,
      -- syslog_level = 'warn',

@@ -111,7 +125,18 @@
          peers = {
          },

          -- Optional: nested peer groups
          -- groups = {
            -- backbone_sub = {
              -- ...
            -- },
          -- ...
          -- },
        },
        -- Optional: additional peer groups, possibly with other limits
        -- backbone2 = {
          -- ...
        -- },
      },
    },

@@ -128,7 +153,8 @@
  },

  autoupdater = {
    -- Default branch. Don't forget to set GLUON_BRANCH when building!
    -- Default branch (optional), can be overridden by setting GLUON_AUTOUPDATER_BRANCH when building.
    -- Set GLUON_AUTOUPDATER_ENABLED to enable the autoupdater by default for newly installed nodes.
    branch = 'stable',

    -- List of branches. You may define multiple branches.
@@ -143,7 +169,7 @@
        -- Have multiple maintainers sign your build and only
        -- accept it when a sufficient number of them have
        -- signed it.
        good_signatures = 2,
        good_signatures = 0,

        -- List of public keys of maintainers.
        pubkeys = {
+1 −0
Original line number Diff line number Diff line
../minimal-site/i18n
 No newline at end of file
Original line number Diff line number Diff line
features {
	'autoupdater',
	'ebtables-filter-multicast',
	'ebtables-filter-ra-dhcp',
	'ebtables-limit-arp',
	'mesh-olsrd',
	'mesh-vpn-fastd',
	'respondd',
	'status-page',
	'web-advanced',
	'web-wizard',
}

packages {
	'iwinfo',
}

if not device_class('tiny') then
	features {'wireless-encryption-wpa3'}
end
+1 −0
Original line number Diff line number Diff line
../minimal-site/modules
 No newline at end of file
+176 −0
Original line number Diff line number Diff line
-- This is an example site configuration
--
-- Take a look at the documentation located at
-- https://gluon.readthedocs.io/ for details.
--
-- This configuration will not work as is. You're required to make
-- community specific changes to it!
{
  -- Used for generated hostnames, e.g. freifunk-abcdef123456. (optional)
  -- hostname_prefix = 'freifunk-',

  -- Name of the community.
  site_name = 'Continuous Integration',

  -- Shorthand of the community.
  site_code = 'ci',

  -- 32 bytes of random data, encoded in hexadecimal
  -- This data must be unique among all sites and domains!
  -- Can be generated using: echo $(hexdump -v -n 32 -e '1/1 "%02x"' </dev/urandom)
  domain_seed = 'e9608c4ff338b920992d629190e9ff11049de1dfc3f299eac07792dfbcda341c',

  -- Prefixes used by clients within the mesh.
  -- prefix6 is required, prefix4 can be omitted if next_node.ip4
  -- is not set.
  prefix6 = 'fdff:cafe:cafe:cafe::/64',

  -- Prefixes used by nodes within the mesh
  node_prefix6 = 'fdff:cafe:cafe:cafe::/64',

  -- Timezone of your community.
  -- See https://openwrt.org/docs/guide-user/base-system/system_configuration#time_zones
  timezone = 'CET-1CEST,M3.5.0,M10.5.0/3',

  -- List of NTP servers in your community.
  -- Must be reachable using IPv6!
  --  ntp_servers = {'1.ntp.services.ffxx'},

  -- Wireless regulatory domain of your community.
  regdom = 'DE',

  -- Wireless configuration for 2.4 GHz interfaces.
  wifi24 = {
    -- Wireless channel.
    channel = 1,

    -- ESSIDs used for client network.
    ap = {
      ssid = 'gluon-ci-ssid',
      -- disabled = true, -- (optional)

      -- Configuration for a backward compatible OWE network below.
      owe_ssid = 'owe.gluon-ci-ssid', -- (optional - SSID for OWE client network)
      owe_transition_mode = true, -- (optional - enables transition-mode - requires ssid as well as owe_ssid)
    },

    mesh = {
      -- Adjust these values!
      id = 'ueH3uXjdp', -- usually you don't want users to connect to this mesh-SSID, so use a cryptic id that no one will accidentally mistake for the client WiFi
      mcast_rate = 12000,
      -- disabled = true, -- (optional)
    },
  },

  -- Wireless configuration for 5 GHz interfaces.
  -- This should be equal to the 2.4 GHz variant, except
  -- for channel.
  wifi5 = {
    channel = 44,
    outdoor_chanlist = '100-140',
    ap = {
      ssid = 'gluon-ci-ssid',
      -- disabled = true, -- (optional)

      -- Configuration for a backward compatible OWE network below.
      owe_ssid = 'owe.gluon-ci-ssid', -- (optional - SSID for OWE client network)
      owe_transition_mode = true, -- (optional - enables transition-mode - requires ssid as well as owe_ssid)
    },
    mesh = {
      -- Adjust these values!
      id = 'ueH3uXjdp',
      mcast_rate = 12000,
    },
  },


  -- The next node feature allows clients to always reach the node it is
  -- connected to using a known IP address.
  next_node = {
    -- anycast IPs of all nodes
    name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' },
    ip4 = '10.0.0.1',
    ip6 = 'fd::1',
  },

  -- Options specific to routing protocols (optional)
  mesh = {
    vxlan = true,
    olsrd = {},
  },

  mesh_vpn = {
    -- enabled = true,

    fastd = {
      -- Refer to https://fastd.readthedocs.io/en/latest/ to better understand
      -- what these options do.

      -- List of crypto-methods to use.
      methods = {'salsa2012+umac'},
      mtu = 1312,
      -- configurable = true,
      -- syslog_level = 'warn',

      groups = {
        backbone = {
          -- Limit number of connected peers to reduce bandwidth.
          limit = 1,

          -- List of peers.
          peers = {
          },

          -- Optional: nested peer groups
          -- groups = {
            -- backbone_sub = {
              -- ...
            -- },
          -- ...
          -- },
        },
        -- Optional: additional peer groups, possibly with other limits
        -- backbone2 = {
          -- ...
        -- },
      },
    },

    bandwidth_limit = {
      -- The bandwidth limit can be enabled by default here.
      enabled = false,

      -- Default upload limit (kbit/s).
      egress = 200,

      -- Default download limit (kbit/s).
      ingress = 3000,
    },
  },

  autoupdater = {
    -- Default branch (optional), can be overridden by setting GLUON_AUTOUPDATER_BRANCH when building.
    -- Set GLUON_AUTOUPDATER_ENABLED to enable the autoupdater by default for newly installed nodes.
    branch = 'stable',

    -- List of branches. You may define multiple branches.
    branches = {
      stable = {
        name = 'stable',

        -- List of mirrors to fetch images from. IPv6 required!
        mirrors = {'http://1.updates.services.ffhl/stable/sysupgrade'},

        -- Number of good signatures required.
        -- Have multiple maintainers sign your build and only
        -- accept it when a sufficient number of them have
        -- signed it.
        good_signatures = 0,

        -- List of public keys of maintainers.
        pubkeys = {
        },
      },
    },
  },
}
+29 −0
Original line number Diff line number Diff line
##	gluon site.mk makefile example

##	DEFAULT_GLUON_RELEASE
#		version string to use for images
#		gluon relies on
#			opkg compare-versions "$1" '>>' "$2"
#		to decide if a version is newer or not.

DEFAULT_GLUON_RELEASE := 0.6+exp$(shell date '+%Y%m%d')

# Variables set with ?= can be overwritten from the command line

##	GLUON_RELEASE
#		call make with custom GLUON_RELEASE flag, to use your own release version scheme.
#		e.g.:
#			$ make images GLUON_RELEASE=23.42+5
#		would generate images named like this:
#			gluon-ff%site_code%-23.42+5-%router_model%.bin

GLUON_RELEASE ?= $(DEFAULT_GLUON_RELEASE)

# Default priority for updates.
GLUON_PRIORITY ?= 0

# Region code required for some images; supported values: us eu
GLUON_REGION ?= eu

# Languages to include
GLUON_LANGS ?= en de
+25 −11
Original line number Diff line number Diff line
#!/bin/bash
#!/usr/bin/env bash

# Script to output the dependency graph of Gluon's packages
# Limitations:
#  * Works only if directory names and package names are the same (true for all Gluon packages)
#  * Doesn't show dependencies through virtual packages correctly

set -e
@@ -24,19 +23,34 @@ print_dep() {
	echo "$(escape_name "$1") -> $(escape_name "$2");"
}

echo 'digraph G {'

for makefile in ./package/*/Makefile; do
	dir="$(dirname "$makefile")"
	package="$(basename "$dir")"

	deps=$(grep -w DEPENDS "$makefile" | cut -d= -f2 | tr -d +)
print_package() {
	local package="$1" depends="$2"
	# shellcheck disable=SC2086
	set -- $depends

	print_node "$package"
	for dep in $deps; do
	for dep in "$@"; do
		print_node "$dep"
		print_dep "$package" "$dep"
	done
}

make -C openwrt -s prepare-tmpinfo

echo 'digraph G {'

cat ./openwrt/tmp/info/.packageinfo-feeds_gluon_base_* | while read -r key value; do
	case "$key" in
	'Package:')
		package="$value"
		;;
	'Depends:')
		depends="${value//+/}"
		;;
	'@@')
		print_package "$package" "$depends"
		;;
	esac
done | sort -u

popd >/dev/null
+47 −0
Original line number Diff line number Diff line
FROM debian:bookworm-slim

ARG TARGETOS
ARG TARGETARCH

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    ca-certificates \
    clang \
    ecdsautils \
    file \
    gawk \
    git \
    libelf-dev \
    libncurses5-dev \
    libnss-unknown \
    libssl-dev \
    llvm \
    lua-check \
    openssh-client \
    python3 \
    python3-dev \
    python3-pyelftools \
    python3-setuptools \
    qemu-utils \
    rsync \
    shellcheck \
    swig \
    time \
    unzip \
    wget \
    zlib1g-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN mkdir /tmp/ec &&\
    wget -O /tmp/ec/ec-${TARGETOS}-${TARGETARCH}.tar.gz https://github.com/editorconfig-checker/editorconfig-checker/releases/download/2.7.0/ec-${TARGETOS}-${TARGETARCH}.tar.gz &&\
    tar -xvzf /tmp/ec/ec-${TARGETOS}-${TARGETARCH}.tar.gz &&\
    mv bin/ec-${TARGETOS}-${TARGETARCH} /usr/local/bin/editorconfig-checker &&\
    rm -rf /tmp/ec

RUN useradd -m -d /gluon -u 100 -g 100 -o gluon
USER gluon

VOLUME /gluon
WORKDIR /gluon
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ use strict;
use warnings;
use Text::Balanced qw(extract_bracketed extract_delimited extract_tagged);

@ARGV >= 1 || die "Usage: $0 <source direcory>\n";
@ARGV >= 1 || die "Usage: $0 <source directory>\n";


my %stringtable;
Original line number Diff line number Diff line
#!/bin/bash
#!/usr/bin/env bash

set -e
# Script to list all upgrade scripts in a clear manner
@@ -28,7 +28,7 @@ fi

pushd "$(dirname "$0")/.." >/dev/null

find ./package packages -name Makefile | while read -r makefile; do
find ./package packages -name Makefile | grep -v '^packages/packages/' | while read -r makefile; do
	dir="$(dirname "$makefile")"

	pushd "$dir" >/dev/null
@@ -37,13 +37,12 @@ find ./package packages -name Makefile | while read -r makefile; do
	dirname="$(dirname "$dir" | cut -d/ -f 3-)"
	package="$(basename "$dir")"

	for file in "${SUFFIX1}"/*; do
		echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${SUFFIX1})"
	done
	for file in "${SUFFIX2}"/*; do
		echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${SUFFIX2})"
	for file in "${SUFFIX1}"/* "${SUFFIX2}"/*; do
		basename="$(basename "${file}")"
		suffix="$(dirname "${file}")"
		printf "%s\t%s\n" "${basename}" "${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${suffix}/${GREEN}${basename}${RESET}"
	done
	popd >/dev/null
done | sort
done | sort | cut -f2-

popd >/dev/null

contrib/push_pkg.sh

0 → 100755
+149 −0
Original line number Diff line number Diff line
#!/bin/sh

set -e

topdir="$(realpath "$(dirname "${0}")/../openwrt")"

# defaults to qemu run script
ssh_host=localhost
build_only=0
preserve_config=1

print_help() {
	echo "$0 [OPTIONS] PACKAGE_DIR [PACKAGE_DIR] ..."
	echo ""
	echo " -h          print this help"
	echo " -r HOST     use a remote machine as target machine. By default if this"
	echo "             option is not given, push_pkg.sh will use a locally"
	echo "             running qemu instance started by run_qemu.sh."
	echo " -p PORT     use PORT as ssh port (default is 22)"
	echo " -b          build only, do not push"
	echo " -P          do not preserve /etc/config. By default, if a package"
	echo "             defines a config file in /etc/config, this config file"
	echo "             will be preserved. If you specify this flag, the package"
	echo "             default will be installed instead."
	echo ""
	echo ' To change gluon variables, run e.g. "make config GLUON_MINIFY=0"'
	echo ' because then the gluon logic will be triggered, and openwrt/.config'
	echo ' will be regenerated. The variables from openwrt/.config are already'
	echo ' automatically used for this script.'
	echo
}

while getopts "p:r:hbP" opt
do
	case $opt in
		P) preserve_config=0;;
		p) ssh_port="${OPTARG}";;
		r) ssh_host="${OPTARG}"; [ -z "$ssh_port" ] && ssh_port=22;;
		b) build_only=1;;
		h) print_help; exit 0;;
		*) ;;
	esac
done
shift $(( OPTIND - 1 ))

[ -z "$ssh_port" ] && ssh_port=2223

if [ "$build_only" -eq 0 ]; then
	remote_info=$(ssh -p "${ssh_port}" "root@${ssh_host}" '
		source /etc/os-release
		printf "%s\\t%s\\n" "$OPENWRT_BOARD" "$OPENWRT_ARCH"
	')
	REMOTE_OPENWRT_BOARD="$(echo "$remote_info" | cut -f 1)"
	REMOTE_OPENWRT_ARCH="$(echo "$remote_info" | cut -f 2)"

	# check target
	if ! grep -q "CONFIG_TARGET_ARCH_PACKAGES=\"${REMOTE_OPENWRT_ARCH}\"" "${topdir}/.config"; then
		echo "Configured OpenWrt Target is not matching with the target machine!" 1>&2
		echo
		printf "%s" "    Configured architecture: " 1>&2
		grep "CONFIG_TARGET_ARCH_PACKAGES" "${topdir}/.config" 1>&2
		echo "Target machine architecture: ${REMOTE_OPENWRT_ARCH}" 1>&2
		echo 1>&2
		echo "To switch the local with the run with the corresponding GLUON_TARGET:"  1>&2
		echo "  make GLUON_TARGET=... config" 1>&2
		exit 1
	fi
fi

if [ $# -lt 1 ]; then
	echo ERROR: Please specify a PACKAGE_DIR. For example:
	echo
	echo " \$ $0 package/gluon-core"
	exit 1
fi

while [ $# -gt 0 ]; do

	pkgdir="$1"; shift
	echo "Package: ${pkgdir}"

	if ! [ -f "${pkgdir}/Makefile" ]; then
		echo "ERROR: ${pkgdir} does not contain a Makefile"
		exit 1
	fi

	if ! grep -q BuildPackage "${pkgdir}/Makefile"; then
		echo "ERROR: ${pkgdir}/Makefile does not contain a BuildPackage command"
		exit 1
	fi

	opkg_packages="$(make TOPDIR="${topdir}" -C "${pkgdir}" DUMP=1 | awk '/^Package: / { print $2 }')"

	search_package() {
		find "$2" -name "$1_*.ipk" -printf '%f\n'
	}

	make TOPDIR="${topdir}" -C "${pkgdir}" clean
	make TOPDIR="${topdir}" -C "${pkgdir}" compile

	if [ "$build_only" -eq 1 ]; then
		continue
	fi

	# IPv6 addresses need brackets around the ${ssh_host} for scp!
	if echo "${ssh_host}" | grep -q :; then
		BL=[
		BR=]
	fi

	for pkg in ${opkg_packages}; do

		for feed in "${topdir}/bin/packages/${REMOTE_OPENWRT_ARCH}/"*/ "${topdir}/bin/targets/${REMOTE_OPENWRT_BOARD}/packages/"; do
			printf "%s" "searching ${pkg} in ${feed}: "
			filename=$(search_package "${pkg}" "${feed}")
			if [ -n "${filename}" ]; then
				echo found!
				break
			else
				echo not found
			fi
		done

		if [ "$preserve_config" -eq 0 ]; then
			opkg_flags=" --force-maintainer"
		fi

		# shellcheck disable=SC2029
		if [ -n "$filename" ]; then
			scp -O -P "${ssh_port}" "$feed/$filename" "root@${BL}${ssh_host}${BR}:/tmp/${filename}"
			ssh -p "${ssh_port}" "root@${ssh_host}" "
				set -e
				echo Running opkg:
				opkg install --force-reinstall ${opkg_flags} '/tmp/${filename}'
				rm '/tmp/${filename}'
				gluon-reconfigure
			"
		else
			# Some packages (e.g. procd-seccomp) seem to contain BuildPackage commands
			# which do not generate *.ipk files. Till this point, I am not aware why
			# this is happening. However, dropping a warning if the corresponding
			# *.ipk is not found (maybe due to other reasons as well), seems to
			# be more reasonable than aborting. Before this commit, the command
			# has failed.
			echo "Warning: ${pkg}*.ipk not found! Ignoring." 1>&2
		fi

	done
done

contrib/run_qemu.sh

0 → 100755
+15 −0
Original line number Diff line number Diff line
#!/bin/sh

# Note: You can exit the qemu instance by first pressing "CTRL + a" then "c".
#       Then you enter the command mode of qemu and can exit by typing "quit".

qemu-system-x86_64 \
	-d 'cpu_reset' \
	-enable-kvm \
	-gdb tcp::1234 \
	-nographic \
	-netdev user,id=wan,hostfwd=tcp::2223-10.0.2.15:22 \
	-device virtio-net-pci,netdev=wan,addr=0x06,id=nic1 \
	-netdev user,id=lan,hostfwd=tcp::6080-192.168.1.1:80,hostfwd=tcp::2222-192.168.1.1:22,net=192.168.1.100/24 \
	-device virtio-net-pci,netdev=lan,addr=0x05,id=nic2 \
	"$@"
+16 −5
Original line number Diff line number Diff line
@@ -29,11 +29,22 @@ lower="$(mktemp)"

trap 'rm -f "$upper" "$lower"' EXIT

awk 'BEGIN    { sep=0 }
     /^---$/ { sep=1; next }
              { if(sep==0) print > "'"$upper"'";
                else       print > "'"$lower"'"}' \
    "$manifest"
awk 'BEGIN    {
	sep = 0
}

/^---$/ {
	sep = 1;
	next
}

{
	if(sep == 0) {
		print > "'"$upper"'"
	} else {
		print > "'"$lower"'"
	}
}' "$manifest"

ecdsasign "$upper" < "$SECRET" >> "$lower"

+22 −11
Original line number Diff line number Diff line
@@ -21,11 +21,22 @@ upper="$(mktemp)"
lower="$(mktemp)"
ret=1

awk "BEGIN    { sep=0 }
    /^---\$/ { sep=1; next }
              { if(sep==0) print > \"$upper\";
                else       print > \"$lower\"}" \
    "$manifest"
awk 'BEGIN    {
	sep = 0
}

/^---$/ {
	sep = 1;
	next
}

{
	if(sep == 0) {
		print > "'"$upper"'"
	} else {
		print > "'"$lower"'"
	}
}' "$manifest"

while read -r line
do
+3 −0
Original line number Diff line number Diff line
.strike {
	text-decoration: line-through;
}
+20 −9
Original line number Diff line number Diff line
@@ -20,11 +20,11 @@
# -- Project information -----------------------------------------------------

project = 'Gluon'
copyright = '2015-2020, Project Gluon'
copyright = 'Project Gluon'
author = 'Project Gluon'

# The short X.Y version
version = '2020.2+'
version = '2023.2.5'
# The full version, including alpha/beta/rc tags
release = version

@@ -48,7 +48,7 @@ templates_path = ['_templates']
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
source_suffix = {'.rst': 'restructuredtext'}

# The master toctree document.
master_doc = 'index'
@@ -58,7 +58,7 @@ master_doc = 'index'
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = 'en'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@@ -71,6 +71,13 @@ pygments_style = None
# Don't highlight code blocks unless requested explicitly
highlight_language = 'none'

# Ignore links to the config mode, as well as anchors on on hackint, which are
# used to mark channel names and do not exist. Regular links are not effected.
linkcheck_ignore = [
    'http://192.168.1.1',
    'https://chat.hackint.org'
]


# -- Options for HTML output -------------------------------------------------

@@ -89,7 +96,7 @@ html_theme = 'sphinx_rtd_theme'
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
#
# html_static_path = ['_static']
html_static_path = ['_static']

# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@@ -101,6 +108,10 @@ html_theme = 'sphinx_rtd_theme'
#
# html_sidebars = {}

# These paths are either relative to html_static_path
# or fully qualified paths (eg. https://...)
html_css_files = ['css/custom.css']


# -- Options for HTMLHelp output ---------------------------------------------

Original line number Diff line number Diff line
@@ -21,8 +21,9 @@ webbrowser. You're welcome to join us!

.. _#gluon: ircs://irc.hackint.org/#gluon
.. _hackint: https://hackint.org/
.. _webchat: https://webirc.hackint.org/#irc://irc.hackint.org/#gluon
.. _webchat: https://chat.hackint.org/?join=gluon

.. _working-with-repositories:

Working with repositories
-------------------------
@@ -52,6 +53,14 @@ and you can try rebasing it onto the new `base` branch yourself and after that c
Always call `make update-patches` after making changes to a module repository as `make update` will overwrite your
commits, making `git reflog` the only way to recover them!

::

  make refresh-patches

In order to refresh patches when updating feeds or the OpenWrt base, `make refresh-patches` applies and updates all of their patches without installing feed packages to the OpenWrt build system.

This command speeds up the maintenance of updating OpenWrt and feeds.

Development Guidelines
----------------------
Lua should be used instead of sh whenever sensible. The following criteria
@@ -66,9 +75,9 @@ the code in the project is formatted in the same way. The following basic rules
apply:

- use tabs instead of spaces
- trailing whitespaces must be eliminated
- trailing whitespace characters must be eliminated
- files need to end with a final newline
- newlines need to have unix line endings (lf)
- newlines need to have Unix line endings (lf)

To that end we provide a ``.editorconfig`` configuration, which is supported by most
of the editors out there.
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ GLUON_SITE_FEED
    List of site feeds; defined in file *modules* in site config

\*_REPO, \*_BRANCH, \*_COMMIT
    Git repository URL, branch and and
    Git repository URL, branch and
    commit ID of the feeds to use. The branch name may be omitted; the default
    branch will be used in this case.

@@ -79,7 +79,7 @@ patch.sh
    - updating all git submodules

    This solution with a temporary clone ensures that the timestamps of checked
    out files are not changed by any intermedidate patch steps, but only when
    out files are not changed by any intermediate patch steps, but only when
    updating the checkout with the final result. This avoids triggering unnecessary
    rebuilds.

@@ -88,3 +88,17 @@ update.sh
    source and installs it into *packages/* directory. It simply tries to set the *base*
    branch of the cloned repo to the correct commit. If this fails it fetches the
    upstream branch and tries again to set the local *base* branch.

getversion.sh
    Used to determine the version numbers of the repositories of Gluon and the
    site configuration, to be included in the built firmware images as
    */lib/gluon/gluon-version* and */lib/gluon/site-version*.

    By default, this uses ``git describe`` to generate a version number based
    on the last git tag. This can be overridden by putting a file called
    *.scmversion* into the root of the respective repositories.

    A command like ``rm -f .scmversion; echo "$(./scripts/getversion.sh .)" > .scmversion``
    can be used before applying local patches to ensure that the reported
    version numbers refer to an upstream commit ID rather than an arbitrary
    local one after ``git am``.
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ Debugging
Kernel Oops
-----------

Sometimes a running Linux kernel detects an error during runtime that canot
Sometimes a running Linux kernel detects an error during runtime that can't
be corrected.
This usually generates a stack trace that points to the location in the code
that caused the oops.
+210 −136
Original line number Diff line number Diff line
Adding support for new hardware
===============================
Adding hardware support
=======================
This page will give a short overview on how to add support
for new hardware to Gluon.

@@ -7,158 +7,232 @@ Hardware requirements
---------------------
Having an ath9k, ath10k or mt76 based WLAN adapter is highly recommended,
although other chipsets may also work. VAP (multiple SSID) support
is a requirement.

.. _device-class-definition:
with simultaneous AP + Mesh Point (802.11s) operation is required.

Device checklist
----------------
Pull requests adding device support must have the device checklist
included in their description. The checklist assures core functionality
of Gluon is well supported on the device.
The description of pull requests adding device support must include the
`device integration checklist
<https://github.com/freifunk-gluon/gluon/wiki/Device-Integration-checklist>`_.
The checklist ensures that core functionality of Gluon is well supported on the
device.

The checklist can be found in the `wiki <https://github.com/freifunk-gluon/gluon/wiki/Device-Integration-checklist>`_.
.. _device-class-definition:

Device classes
--------------
Gluon currently is aware of two device classes. Depending on the device class, different
features can be installed onto the device.

The ``tiny`` device-class contains devices with the following limitations:

* All devices with less than 64 MB of system memory
* All devices with less than 7 MB of usable firmware space
* Devices using a single ath10k radio and less than 128MB of system memory

.. _hardware-adding-profiles:

Adding profiles
---------------
The vast majority of devices with ath9k WLAN is based on the ar71xx target of OpenWrt.
If the hardware you want to add support for is ar71xx, adding a new profile
is sufficient.

Profiles are defined in ``targets/*`` in a shell-based DSL (so common shell
command syntax like ``if`` can be used).
All supported hardware is categorized into "device classes". This allows to
adjust the feature set of Gluon to the different hardware's capabilities via
``site.mk`` without having to list individual devices.

The ``device`` command is used to define an image build for a device. It takes
two or three parameters.

The first parameter defines the Gluon profile name, which is used to refer to the
device and is part of the generated image name. The profile name must be same as
the output of the following command (on the target device), so the autoupdater
can work::

    lua -e 'print(require("platform_info").get_image_name())'

While porting Gluon to a new device, it might happen that the profile name is
unknown. Best practise is to generate an image first by using an arbitrary value
and then executing the lua command on the device and use its output from then on.

The second parameter defines the name of the image files generated by OpenWrt. Usually,
it is also the OpenWrt profile name; for devices that still use the old image build
code, a third parameter with the OpenWrt profile name can be passed. The profile names
can be found in the image Makefiles in ``openwrt/target/linux/<target>/image/Makefile``.

Examples::

    device tp-link-tl-wr1043n-nd-v1 tl-wr1043nd-v1
    device alfa-network-hornet-ub hornet-ub HORNETUB

Suffixes and extensions
'''''''''''''''''''''''
There are currently two devices classes defined: "standard" and "tiny". The
"tiny" class contains all devices that do not meet the following requirements:

By default, image files are expected to have the extension ``.bin``. In addition,
the images generated by OpenWrt have a suffix before the extension that defaults to
``-squashfs-factory`` and ``-squashfs-sysupgrade``.
- At least 7 MiB of usable firmware space
- At least 64 MiB of RAM (128MiB for devices with ath10k radio)

This can be changed using the ``factory`` and ``sysupgrade`` commands, either at
the top of the file to set the defaults for all images, or for a single image. There
are three forms with 0 to 2 arguments (all work with ``sysupgrade`` as well)::
Target configuration
--------------------
Gluon's hardware support is based on OpenWrt's. For each supported target,
a configuration file exists at ``targets/<target>-<subtarget>`` (or just
``target/<target>`` for targets without subtargets) that contains all
Gluon-specific settings for the target. The generic configuration
``targets/generic`` contains settings that affect all targets.

    factory SUFFIX .EXT
    factory .EXT
    factory
All targets must be listed in ``target/targets.mk``.

When only an extension is given, the default suffix is retained. When no arguments
are given, this signals that no factory (or sysupgrade) image exists.
The target configuration language is based on Lua, so Lua's syntax for variables
and control structures can be used.

Aliases
'''''''
Device definitions
~~~~~~~~~~~~~~~~~~
To configure a device to be built for Gluon, the ``device`` function is used.
In the simplest case, only two arguments are passed, for example:

Sometimes multiple models use the same OpenWrt images. In this case, the ``alias``
command can be used to create symlinks and additional entries in the autoupdater
manifest for the alternative models.
.. code-block:: lua

Standalone images
'''''''''''''''''
  device('tp-link-tl-wdr3600-v1', 'tplink_tl-wdr3600-v1')

On targets without *per-device rootfs* support in OpenWrt, the commands described above
can't be used. Instead, ``factory_image`` and ``sysupgrade_image`` are used::
The first argument is the device name in Gluon, which is part of the output
image filename, and must correspond to the model string looked up by the
autoupdater. The second argument is the corresponding device profile name in
OpenWrt, as found in ``openwrt/target/linux/<target>/image/*``.

    factory_image PROFILE IMAGE .EXT
    sysupgrade_image PROFILE IMAGE .EXT
A table of additional settings can be passed as a third argument:

Again, the profile name must match the value printed by the aforementioned Lua
command. The image name must match the part between the target name and the extension
as generated by OpenWrt and is to be omitted when no such part exists.
.. code-block:: lua

Packages
''''''''
  device('ubiquiti-edgerouter-x', 'ubnt_edgerouter-x', {
    factory = false,
    packages = {'-hostapd-mini'},
    manifest_aliases = {
      'ubnt-erx',
    },
  })

The ``packages`` command takes an arbitrary number of arguments. Each argument
defines an additional package to include in the images in addition to the default
package sets defined by OpenWrt. When a package name is prefixed by a minus sign, the
packages are excluded instead.
The supported additional settings are described in the following sections.

The ``packages`` command may be used at the top of a target definition to modify
the default package list for all images, or just for a single device (when the
target supports *per-default rootfs*).


Configuration
'''''''''''''

The ``config`` command allows to add arbitrary target-specific OpenWrt configuration
to be emitted to ``.config``.

Notes
'''''

On devices with multiple WLAN adapters, care must also be taken that the primary MAC address is
configured correctly. ``/lib/gluon/core/sysconfig/primary_mac`` should contain the MAC address which
can be found on a label on most hardware; if it does not, ``/lib/gluon/upgrade/010-primary-mac``
in ``gluon-core`` might need a fix. (There have also been cases in which the address was incorrect
even on devices with only one WLAN adapter, in these cases a OpenWrt bug was the cause).


Adding support for new hardware targets
---------------------------------------

Adding a new target is much more complex than adding a new profile. There are two basic steps
required for adding a new target:

Package adjustments
'''''''''''''''''''

One package that may need adjustments for new targets is ``libplatforminfo`` (to be found in
`packages/gluon/libs/libplatforminfo <https://github.com/freifunk-gluon/packages/tree/master/libs/libplatforminfo>`_).
If the new platform works fine with the definitions found in ``default.c``, nothing needs to be done. Otherwise,
create a definition for the added target or subtarget, either by symlinking one of the files in the ``templates``
directory, or adding a new source file.

On many targets, Gluon's network setup scripts (mainly in the package ``gluon-core``)
won't run correctly without some adjustments, so better double check that everything is fine there (and the files
``primary_mac``, ``lan_ifname`` and ``wan_ifname`` in ``/lib/gluon/core/sysconfig/`` contain sensible values).

Build system support
''''''''''''''''''''

A definition for the new target must be created under ``targets``, and it must be added
to ``targets/targets.mk``. The ``GluonTarget`` macro takes one to three arguments:
the target name, the Gluon subtarget name (if the target has subtargets), and the
OpenWrt subtarget name (if it differs from the Gluon subtarget). The third argument
can be used to define multiple Gluon targets with different configuration for the
same OpenWrt target, like it is done for the ``ar71xx-tiny`` target.

After this, is should be sufficient to call ``make GLUON_TARGET=<target>`` to build the images for the new target.
Suffixes and extensions
~~~~~~~~~~~~~~~~~~~~~~~
For many targets, OpenWrt generates images with the suffixes
``-squashfs-factory.bin`` and ``-squashfs-sysupgrade.bin``. For devices with
different image names, is it possible to override the suffixes and extensions
using the settings ``factory``, ``factory_ext``, ``sysupgrade`` and
``sysupgrade_ext``, for example:

.. code-block:: lua

  {
    factory = '-squashfs-combined',
    factory_ext = '.img.gz',
    sysupgrade = '-squashfs-combined',
    sysupgrade_ext = '.img.gz',
  }

Only settings that differ from the defaults need to be passed. ``factory`` and
``sysupgrade`` can be set to ``false`` when no such images exist.

For some device types, there are multiple factory images with different
extensions. ``factory_ext`` can be set to a table of strings to account for this
case:

.. code-block:: lua

  {
    factory_ext = {'.img.gz', '.vmdk', '.vdi'},
  }

TODO: Extra images

Aliases and manifest aliases
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes multiple devices exist that use the same OpenWrt images. To make it
easier to find these images, the ``aliases`` setting can be used to define
additional device names. Gluon will create symlinks for these names in the
image output directory.

.. code-block:: lua

  device('aruba-ap-303', 'aruba_ap-303', {
    factory = false,
    aliases = {'aruba-instant-on-ap11'},
  })

The aliased name will also be added to the autoupdater manifest, allowing upgrade
images to be found under the different name on targets that perform model name
detection at runtime.

It is also possible to add alternative names to the autoupdater manifest without
creating a symlink by using ``manifest_aliases`` instead of ``aliases``, which
should be done when the alternative name does not refer to a separate device.
This is particularly useful to allow the autoupdater to work when the model name
changed between Gluon versions.

Package lists
~~~~~~~~~~~~~
Gluon generates lists of packages that are installed in all images based on a
default list and the features and packages specified in the site configuration.

In addition, OpenWrt defines additional per-device package lists. These lists
may be modified in Gluon's device definitions, for example to include additional
drivers and firmware, or to remove unneeded software. Packages to remove are
prefixed with a ``-`` character.

For many ath10k-based devices, this is used to replace the "CT" variant of
ath10k with the mainline-based version:

.. code-block:: lua

  local ATH10K_PACKAGES_QCA9880 = {
    'kmod-ath10k',
    '-kmod-ath10k-ct',
    '-kmod-ath10k-ct-smallbuffers',
    'ath10k-firmware-qca988x',
    '-ath10k-firmware-qca988x-ct',
  }
  device('openmesh-a40', 'openmesh_a40', {
    packages = ATH10K_PACKAGES_QCA9880,
    factory = false,
  })

This example also shows how to define a local variable, allowing the package
list to be reused for multiple devices.

Device flags
~~~~~~~~~~~~

The settings ``class``, ``deprecated`` or ``broken`` should be set according to
the device support status. The default values are as follows:

.. code-block:: lua

  {
    class = 'standard',
    deprecated = false,
    broken = false,
  }

- Device classes are described in :ref:`device-class-definition`
- Broken devices are untested or do not meet our requirements as given by the
  device checklist
- Deprecated devices are slated for removal in a future Gluon version due to
  hardware constraints

Global settings
~~~~~~~~~~~~~~~
There is a number of directives that can be used outside of a ``device()``
definition:

- ``include('filename')``: Include another file with global settings
- ``config(key, value)``: Set a config symbol in OpenWrt's ``.config``. Value
  may be a string, number, boolean, or nil. Booleans and nil are used for
  tristate symbols, where nil sets the symbol to ``m``.
- ``try_config(key, value)``: Like ``config()``, but do not fail if setting
  the symbol is not possible (usually because its dependencies are not met)
- ``packages { 'package1', '-package2', ... }``: Define a list of packages to
  add or remove for all devices of a target. Package lists passed to multiple
  calls of ``packages`` will be aggregated.
- ``defaults { key = value, ... }``: Set default values for any of the
  additional settings that can be passed to ``device()``.

Helper functions
~~~~~~~~~~~~~~~~
The following helpers can be used in the target configuration:

- ``env.KEY`` allows to access environment variables
- ``istrue(value)`` returns true if the passed string is a positive number
  (often used with ``env``, for example ``if istrue(env.GLUON_DEBUG) then ...``)

Hardware support in packages
----------------------------
In addition to the target configuration files, some device-specific changes may
be required in packages.

gluon-core
~~~~~~~~~~
- ``/lib/gluon/upgrade/010-primary-mac``: Override primary MAC address selection

  Usually, the primary (label) MAC address is defined in OpenWrt's Device Trees.
  For devices or targets where this is not the case, it is possible to specify
  what interface to take the primary MAC address from in ``010-primary-mac``.

- ``/lib/gluon/upgrade/020-interfaces``: Override LAN/WAN interface assignment

  On PoE-powered devices, the PoE input port should be "WAN".

- ``/usr/lib/lua/gluon/platform.lua``: Contains a list of outdoor devices

gluon-setup-mode
~~~~~~~~~~~~~~~~
- ``/lib/gluon/upgrade/320-setup-ifname``: Contains a list of devices that use
  the WAN port for the config mode

  On PoE-powered devices, the PoE input port should be used for the config
  mode. This is handled correctly by default for outdoor devices listed in
  ``platform.lua``.

libplatforminfo
~~~~~~~~~~~~~~~
When adding support for a new target to Gluon, it may be necessary to adjust
libplatforminfo to define how autoupdater image names are derived from the
model name.
Original line number Diff line number Diff line
@@ -3,6 +3,88 @@ Package development

Gluon packages are OpenWrt packages and follow the same rules described at https://openwrt.org/docs/guide-developer/packages.

Development workflow
====================

When you are developing packages, it often happens that you iteratively want to deploy
and verify the state your development. There are two ways to verify your changes:

1)
  One way is to rebuild the complete firmware, flash it, configure it and verify your
  development then. This usually takes at least a few minutes to get your changes
  working so you can test them. Especially if you iterate a lot, this becomes tedious.

2)
  Another way is to rebuild only the package you are currently working on and
  to deploy this package to your test system. Here not even a reboot is required.
  This makes iterating relatively fast. Your test system could be real hardware or
  even a qemu in most cases.

Gluon provides scripts to enhance workflow 2). Here is an example illustrating
the workflow using these scripts:

.. code-block:: shell

  # start a local qemu instance
  contrib/run_qemu.sh output/images/factory/[...]-x86-64.img

  # apply changes to the desired package
  vi package/gluon-ebtables/files/etc/init.d/gluon-ebtables

  # rebuild and push the package to the qemu instance
  contrib/push_pkg.sh package/gluon-ebtables/

  # test your changes
  ...

  # do more changes
  ...

  # rebuild and push the package to the qemu instance
  contrib/push_pkg.sh package/gluon-ebtables/

  # test your changes
  ...

  (and so on...)

  # see help of the script for more information
  contrib/push_pkg.sh -h
  ...

Features of ``push_pkg.sh``:

* Works with compiled and non-compiled packages.

  * This means it can be used in the development of C-code, Lua-Code and mostly any other code.

* Works with native OpenWrt and Gluon packages.
* Pushes to remote machines or local qemu instances.
* Pushes multiple packages in one call if desired.
* Performs site.conf checks.

Implementation details of ``push_pkg.sh``:

* First, the script builds an opkg package using the OpenWrt build system.
* This package is pushed to a *target machine* using scp:

  * By default the *target machine* is a locally running x86 qemu started using ``run_qemu.sh``.
  * The *target machine* can also be remote machine. (See the cli switch ``-r``)
  * Remote machines are not limited to a specific architecture. All architectures supported by gluon can be used as remote machines.

* Finally opkg is used to install/update the packages in the target machine.

  * While doing this, it will not override ``/etc/config`` with package defaults by default. (See the cli switch ``-P``).
  * While doing this, opkg calls the ``check_site.lua`` from the package as post_install script to validate the ``site.conf``. This means that the ``site.conf`` of the target machine is used for this validation.

Note that:

* ``push_pkg.sh`` does neither build nor push dependencies of the packages automatically. If you want to update dependencies, you must explicitly specify them to be pushed.
* If you add new packages, you must run ``make update config GLUON_TARGET=...``.
* You can change the gluon target of the target machine via ``make config GLUON_TARGET=...``.
* If you want to update the ``site.conf`` of the target machine, use ``push_pkg.sh package/gluon-site/``.
* Sometimes when things break, you can heal them by compiling a package with its dependencies: ``cd openwrt; make package/gluon-ebtables/clean; make package/gluon-ebtables/compile; cd ..``.
* You can exit qemu by pressing ``CTRL + a`` and ``c`` afterwards.

Gluon package makefiles
=======================
@@ -72,7 +154,8 @@ Feature flags

Feature flags provide a convenient way to define package selections without
making it necessary to list each package explicitly. The list of features to
enable for a Gluon build is set by the *GLUON_FEATURES* variable in *site.mk*.
enable for a Gluon build is determined by the evaluated image-customization.lua file
in the root-directory of the Site repository.

The main feature flag definition file is ``package/features``, but each package
feed can provide additional definitions in a file called ``features`` at the root
@@ -82,51 +165,51 @@ Each flag *$flag* will include the package the name *gluon-$flag* by default.
The feature definition file can modify the package selection by adding or removing
packages when certain combinations of flags are set.

Feature definitions use Lua syntax. The function *feature* has two arguments:
Feature definitions use Lua syntax. Two basic functions are defined:

* *feature(name, pkgs)*: Defines a new feature. *feature()* expects a feature
  (flag) name and a list of packages to add or remove when the feature is
  enabled.

  * Defining a feature using *feature* replaces the default definition of
    just including *gluon-$flag*.
  * A package is removed when the package name is prefixed with a ``-`` (after
    the opening quotation mark).

* A logical expression composed of feature flag names (each prefixed with an underscore before the opening
  quotation mark), logical operators (*and*, *or*, *not*) and parantheses
* A table with settings that are applied when the logical expression is
  satisfied:
* *when(expr, pkgs)*: Adds or removes packages when a given logical expression
  of feature flags is satisfied.

  * Setting *nodefault* to *true* suppresses the default of including the *gluon-$flag* package.
    This setting is only applicable when the logical expression is a single,
    non-negated flag name.
  * The *packages* field adds or removes packages to install. A package is
    removed when the package name is prefixed with a ``-`` (after the opening
    quotation mark).
  * *expr* is a logical expression composed of feature flag names (each prefixed
    with an underscore before the opening quotation mark), logical operators
    (*and*, *or*, *not*) and parentheses.
  * Referencing a feature flag in *expr* has no effect on the default handling
    of the flag. When no *feature()* entry for a flag exists, it will still
    add *gluon-$flag* by default.
  * *pkgs* is handled as for *feature()*.

Example::

    feature(_'web-wizard', {
      nodefault = true,
      packages = {
    feature('web-wizard', {
      'gluon-config-mode-hostname',
      'gluon-config-mode-geo-location',
      'gluon-config-mode-contact-info',
      'gluon-config-mode-outdoor',
      },
    })

    feature(_'web-wizard' and (_'mesh-vpn-fastd' or _'mesh-vpn-tunneldigger'), {
      packages = {
    when(_'web-wizard' and _'mesh-vpn-fastd' or _'mesh-vpn-wireguard'), {
      'gluon-config-mode-mesh-vpn',
      },
    })

    feature(_'no-radvd', {
      nodefault = true,
      packages = {
    feature('no-radvd', {
      '-gluon-radvd',
      },
    })


This will

* disable the inclusion of the (non-existent) packages *gluon-web-wizard* and *gluon-no-radvd* when their
  corresponding feature flags appear in *GLUON_FEATURES*
  corresponding feature flags are evaluated as selected in the image-customization.lua file
* enable four additional config mode packages when the *web-wizard* feature is enabled
* enable *gluon-config-mode-mesh-vpn* when both *web-wizard* and one
  of *mesh-vpn-fastd* and *mesh-vpn-tunneldigger* are enabled
  of *mesh-vpn-fastd* and *mesh-vpn-wireguard* are enabled
* disable the *gluon-radvd* package when *gluon-no-radvd* is enabled
Original line number Diff line number Diff line
WAN support
===========
Uplink support
==============

As the WAN port of a node will be connected to a user's private network, it
is essential that the node only uses the WAN when it is absolutely necessary.
@@ -11,11 +11,12 @@ There are two cases in which the WAN port is used:
After the VPN connection has been established, the node should be able to reach
the mesh's DNS servers and use these for all other name resolution.

If the device does not feature a WAN port, the LAN port is configured as WAN port.
In case such a device has multiple LAN ports, all these can be used as WAN.
Devices, which feature a "hybrid" port (labled as WAN/LAN), this port is used as WAN.

This behavior can be reversed using the ``single_as_lan`` site.conf option.
If a device has only a single Ethernet port (or group of ports), it will be
used as an uplink port even when it is not labeled as "WAN" by default. This
behavior can be controlled using the ``interfaces.single.default_roles``
site.conf option. It is also possible to alter the interface assignment after
installation by modifying ``/etc/config/gluon`` and running
``gluon-reconfigure``.

Routing tables
~~~~~~~~~~~~~~
Original line number Diff line number Diff line
@@ -11,18 +11,28 @@ gluon-config-mode-core
gluon-config-mode-hostname
    Provides a hostname field.

gluon-config-mode-autoupdater
:doc:`gluon-config-mode-autoupdater <../../features/autoupdater>`
    Informs whether the autoupdater is enabled.

gluon-config-mode-mesh-vpn
    Allows toggling of mesh-vpn-fastd and setting a bandwidth limit.
:doc:`gluon-config-mode-mesh-vpn <../../features/vpn>`
    Allows toggling of installed mesh-vpn technology and setting a bandwidth limit.

gluon-config-mode-geo-location
    Enables the user to set the geographical location of the node.

:doc:`../../package/gluon-config-mode-geo-location-osm`
    Lets the user click on a map to select the geographical location through a OSM map

gluon-config-mode-contact-info
    Adds a field where the user can provide contact information.

:doc:`../../package/gluon-web-cellular`
    Adds advanced options to enter WWAN config.

:doc:`../../package/gluon-web-network`
    Adds option to configure used role on interfaces

Most of the configuration options are described in :ref:`user-site-config_mode`

Writing Config Mode modules
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Original line number Diff line number Diff line
@@ -74,8 +74,7 @@ Useful functions:
  - *header* (*key*, *value*): Adds an HTTP header to the reply to be sent to
    the client. Has no effect when non-header data has already been written.
  - *prepare_content* (*mime*): Sets the *Content-Type* header to the given MIME
    type, potentially setting additional headers or modifying the MIME type to
    accommodate browser quirks
    type
  - *write* (*data*, ...): Sends the given data to the client. If headers have not
    been sent, it will be done before the data is written.

Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ Let's start with an example:

  return f

The toplevel element of a model is always a *Form*, but it is also possible for
The top-level element of a model is always a *Form*, but it is also possible for
a model to return multiple forms, which are displayed one below the other.

A *Form* has one or more *Sections*, and each *Section* has different types
Original line number Diff line number Diff line
@@ -7,8 +7,11 @@ Building Images
---------------

By default, the autoupdater is disabled (as it is usually not helpful to have unexpected updates
during development), but it can be enabled by setting the variable GLUON_BRANCH when building
to override the default branch set in the site configuration.
during development), but it can be enabled by setting the variable ``GLUON_AUTOUPDATER_ENABLED`` to ``1`` when building.
It is also possible to override the default branch during build using the variable ``GLUON_AUTOUPDATER_BRANCH``.

If a default branch is set neither in *site.conf* nor via ``GLUON_AUTOUPDATER_BRANCH``, the default branch is
implementation-defined. Currently, the branch with the first name in alphabetical order is chosen.

A manifest file for the updater can be generated with `make manifest`. A signing script (using
``ecdsautils``) can be found in the `contrib` directory. When creating the manifest, the
@@ -27,20 +30,68 @@ in ``site.mk``, care must be taken to pass the same ``GLUON_RELEASE`` to ``make
as otherwise the generated manifest will be incomplete.


Manifest format
---------------

The manifest starts with a short header, followed by the list of firmwares and signatures.
The header contains the following information:

.. code-block:: sh

    BRANCH=stable
    DATE=2020-10-07 00:00:00+02:00
    PRIORITY=7

- ``BRANCH`` is the autoupdater branch name that needs to match the nodes configuration.
- ``DATE`` specifies when the time period for the update begins. Nodes will do their regular update during a random minute
  between 4:00 and 4:59 am. Nodes might not always have a reliable NTP synchronization, which is why a fallback mechanism
  exists, that checks for an update, and will execute if ``DATE`` is at least 24h in the past.
- ``PRIORITY`` can be configured as ``GLUON_PRIORITY`` when generating the manifest or in ``site.mk``, and defines
  the number of days over which the update should be stretched out after ``DATE``. Nodes will calculate a probability
  based on the time left to determine when to update.

Signing images
--------------

As noted above, manifest files can be signed by an arbitrary amount of ECDSA keys.
The amount of valid signatures required to have the autoupdater accept an image is configured using the :ref:`site.conf <user-site-autoupdater>`.

A secret key (that like an SSH private key must never be shared) can be generated like this:

.. code-block:: sh

    mkdir ~/.ecdsa/
    ( umask 077 && ecdsautil generate-key > ~/.ecdsa/id_y25519 )

This is then used to derive a public key, meant to be placed in the ``site.conf``.

.. code-block:: sh

    ( umask 033 && ecdsautil show-key < ~/.ecdsa/id_y25519 > ~/.ecdsa/id_y25519.pub )

A manifest can then be signed using the helper in gluons `contrib` directory.

.. code-block:: sh

    ./contrib/sign.sh ~/.ecdsa/id_y25519 output/images/sysupgrade/stable.manifest

In the manifest file only the content above the three dashes is signed, not other signatures that might exist.

Automated nightly builds
------------------------

A fully automated nightly build could use the following commands:

::
.. code-block:: sh

    git pull
    (git -C site pull)
    # git -C site pull
    make update
    make clean GLUON_TARGET=ar71xx-generic
    make clean GLUON_TARGET=ath79-generic
    NUM_CORES_PLUS_ONE=$(expr $(nproc) + 1)
    make -j$NUM_CORES_PLUS_ONE GLUON_TARGET=ar71xx-generic GLUON_BRANCH=experimental GLUON_RELEASE=$GLUON_RELEASE
    make manifest GLUON_BRANCH=experimental GLUON_RELEASE=$GLUON_RELEASE
    make -j$NUM_CORES_PLUS_ONE GLUON_TARGET=ath79-generic GLUON_RELEASE=$GLUON_RELEASE \
        GLUON_AUTOUPDATER_BRANCH=experimental GLUON_AUTOUPDATER_ENABLED=1
    make manifest GLUON_RELEASE=$GLUON_RELEASE GLUON_AUTOUPDATER_BRANCH=experimental
    contrib/sign.sh $SECRETKEY output/images/sysupgrade/experimental.manifest

    rm -rf /where/to/put/this/experimental
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ Config Mode by pressing and holding the RESET/WPS/DECT button for about three
seconds. The device should reboot (all LEDs will turn off briefly) and
Config Mode will be available.

If you have access to the console of the node, there is the
``gluon-enter-setup-mode`` command, which reboots a node into Config Mode.


Port Configuration
------------------
@@ -35,3 +38,17 @@ Accessing Config Mode
Config Mode can be accessed at http://192.168.1.1. The node will offer DHCP
to clients. Should this fail, you may assign an IP from 192.168.1.0/24 to
your computer manually.

.. image:: configmode.png

Advanced Config Options
-----------------------

Depending on the installed packages, the advanced config mode allows to configure packages further.

* :doc:`gluon-web-wifi-config enable <wlan-configuration>` radios used for wifi and mesh as well as outdoor mode
* :doc:`../package/gluon-web-network` allows to configure the used roles (uplink, mesh, client) on each interface
* :doc:`../package/gluon-web-admin` allows to enter SSH keys or set a password in the `Remote access` section
* :doc:`../package/gluon-web-cellular` allows to configure SIM card / WWAN settings on supported cellular devices

The advanced config does also allow to upload a sysupgrade file to update the firmware to a different version.
+53 −0
Original line number Diff line number Diff line
.. _dns-caching:

DNS caching
===========

User experience may be greatly improved when dns is accelerated. Also, it
seems like a good idea to keep the number of packages being exchanged
between node and gateway as small as possible. In order to do this, a
DNS cache may be used on a node. The dnsmasq instance listening on port
53 on the node will be reconfigured to answer requests, use a list of
upstream servers and a specific cache size if the options listed below are
added to site.conf. Upstream servers are the DNS servers which are normally
used by the nodes to resolve hostnames (e.g. gateways/supernodes).

There are the following settings:
    servers
    cacheentries

To use the node's DNS server, both options should be set. The node will cache at
most 'cacheentries' many DNS records in RAM. The 'servers' list will be used to
resolve the received DNS queries if the request cannot be answered from
cache. Gateways should announce the "next node" address via DHCP and RDNSS (if
any). Note that not setting 'servers' here will lead to DNS not working: Once
the gateways all announce the "next node" address for DNS, there is no way for
nodes to automatically determine DNS servers. They have to be baked into the
firmware.

If these settings do not exist, the cache is not initialized and RAM usage will
not increase.

When next_node.name is set, an A record and an AAAA record for the
next-node IP address are placed in the dnsmasq configuration. This means that
the content of next_node.name may be resolved even without upstream connectivity.
It is suggested to use the same name as the DNS server provides:
e.g. nextnode.location.community.example.org (This way the name also works if a
client uses static DNS Servers). Hint: If next_node.name does not contain a dot
some browsers would open the searchpage instead.

::

  dns = {
    cacheentries = 5000,
    servers = { '2001:4860:4860::8888', '2001:4860:4860::8844' },
  },

  next_node = {
    name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' },
    ip6 = '2001:db8:8::1',
    ip4 = '198.51.100.1',
  }


Each cache entry will occupy about 90 bytes of RAM.

docs/features/dns-forwarder.rst

deleted100644 → 0
+0 −26
Original line number Diff line number Diff line
DNS forwarder
=============

A Gluon node can be configured to act as a DNS forwarder. Requests for the
next-node hostname(s) can be answered locally, without querying the upstream
resolver.

**Note:** While this reduces answer time and allows to use the next-node
hostname without upstream connectivity, this feature should not be used for
next-node hostnames that are FQDN when the zone uses DNSSEC.

One or more upstream resolvers can be configured in the *dns.servers* setting.
When *next_node.name* is set, A and/or AAAA records for the next-node IP
addresses are placed in the dnsmasq configuration.

::

  dns = {
    servers = { '2001:db8::1', },
  },

  next_node = {
    name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' },
    ip6 = '2001:db8:8::1',
    ip4 = '198.51.100.1',
  }
Original line number Diff line number Diff line
@@ -135,5 +135,5 @@ Adding a data provider
----------------------

To add a provider, you need to install a shared object into ``/lib/gluon/respondd``.
For more information, refer to the `respondd README <https://github.com/freifunk-gluon/packages/blob/master/net/respondd/README.md>`_
For more information, refer to the `respondd README <https://github.com/freifunk-gluon/packages/blob/main/net/respondd/README.md>`_
and have a look the existing providers.
Original line number Diff line number Diff line
@@ -88,18 +88,25 @@ domain of a router, if and only if one of the above conditions matches.
Switching the domain
--------------------

**via commandline**:
Via commandline
^^^^^^^^^^^^^^^

::

    uci set gluon.core.domain="newdomaincode"
    gluon-reconfigure
    reboot
  gluon-switch-domain 'newdomaincode'

**via config mode:**
When the node is not in config mode, ``gluon-switch-domain`` will automatically
reboot the node by default. This can be suppressed by passing ``--no-reboot``::

To allow switching the domain via config mode, ``config-mode-domain-select``
has to be added to GLUON_FEATURES in the site.mk.
  gluon-switch-domain --no-reboot 'newdomaincode'

Switching the domain without reboot is currently **experimental**.

Via config mode
^^^^^^^^^^^^^^^

To allow switching the domain via config mode, add ``config-mode-domain-select``
to the enabled features in the image-customization.lua file.

|image0|

@@ -123,13 +130,10 @@ site.conf only variables
  - authorized_keys
  - default_domain
  - poe_passthrough
   -  mesh_on_wan
   -  mesh_on_lan
   -  single_as_lan
  - interfaces.*.default_roles
  - setup_mode.skip
  - autoupdater.branch
  - mesh_vpn.enabled
   -  mesh_vpn.pubkey_privacy
  - mesh_vpn.bandwidth_limit
  - mesh_vpn.bandwidth_limit.enabled
  - mesh_vpn.bandwidth_limit.ingress
@@ -181,7 +185,7 @@ domain.conf only variables
      - ``true``, ``false``
      - ``{ 'foo', 'bar' }``

-  Because each domain is considered as an own layer 2 network, these
- Because each domain is considered a separate layer 2 network, these
  values should be different in each domain:

  - next_node.ip4
@@ -201,7 +205,6 @@ domain.conf only variables
  - wifi*.mesh.id
  - mesh_vpn.fastd.groups.*.peers.remotes
  - mesh_vpn.fastd.groups.*.peers.key
   -  mesh_vpn.tunneldigger.brokers

- Clients consider WiFi networks sharing the same ESSID as if they were
  the same L2 network and try to reconfirm and reuse previous
Original line number Diff line number Diff line
Private WLAN
============

It is possible to set up a private WLAN that bridges the WAN port and is separated from the mesh network.
Please note that you should not enable ``mesh_on_wan`` simultaneously.
It is possible to set up a private WLAN that bridges the uplink port and is separated from the mesh network.
Please note that you should not enable Wired Mesh on the uplink port at the same time.

The private WLAN is encrypted using WPA2 by default. On devices with enough flash and a supported radio,
WPA3 or WPA2/WPA3 mixed-mode can be used instead of WPA2. For this to work, the ``wireless-encryption-wpa3``
feature has to be added to ``GLUON_FEATURES``.
feature has to be enabled as a feature.

It is recommended to enable IEEE 802.11w management frame protection for WPA2/WPA3 networks, however this
can lead to connectivity problems for older clients. In this case, management frame protection can be
@@ -27,7 +27,7 @@ You may also enable a private WLAN using the command line::
  uci set wireless.wan_radio$RID.ssid="$SSID"
  uci set wireless.wan_radio$RID.key="$KEY"
  uci set wireless.wan_radio$RID.disabled=0
  uci set wireless.wan_radio$RID.macaddr=$(lua -e "print(require('gluon.util').generate_mac(3+4*$RID))")
  uci set wireless.wan_radio$RID.macaddr=$(lua -e "print(require('gluon.wireless').get_wlan_mac('wan_radio', $RID))")
  uci commit
  wifi

+30 −0
Original line number Diff line number Diff line
Status-Page
===========

When the feature ``gluon-status-page`` is enabled, Gluon nodes run a HTTP server with status information on all IP addresses of ``br-client``.
This makes it possible to check information of the node in realtime.

If the mesh protocol ``gluon-mesh-batman-adv`` is installed too, the package ``gluon-status-page-mesh-batman-adv`` is added too according to the :ref:`user-site-feature-flags`

.. _status-page-example-picture:

Example Picture
---------------

The left side of the status page contains Overview information.
In the middle, current monitoring information abut the system, number of clients, radios, amount of traffic and connected mesh-vpn if any are shown.
The right side of the Status-Page contains information about Neighbours to this node through :doc:`wired-mesh` as well as wireless mesh.

.. image:: status-page.png

Mesh Graphs
-----------

When wireless mesh is enabled, the mesh interfaces show realtime Graphs about the received signal strength (RSSI) in dBm.

Neighbours
----------

The list of neighbours at first shows the mac-address of the neighbour it sees.
The status-page sends a second request to ``http://[ipv6]/cgi-bin/dyn/neighbours-nodeinfo?mesh-vpn`` which triggers the lookup of neighbour information on the node itself.
Through this, the actual nodenames of the neighbours are shown on the status-page as can be seen in the :ref:`status-page-example-picture`.

docs/features/tls.rst

0 → 100644
+10 −0
Original line number Diff line number Diff line
TLS support
===========

The generic TLS implementation which is currently used by OpenWRT can be installed or added as dependency through the package ``gluon-tls``.
This removes the need for community packages to depend on a specific TLS implementation (like mbedtls, OpenSSL or WolfSSL).

This package is an alias for the current TLS implementation used.
To allow for easy usage of communicating through HTTPS from the node, typical Certificate Authorities (CAs) are included through the package ``ca-bundle`` .

* Starting with OpenWRT 23.05, mbedtls is the default TLS layer - this is reflected in Gluon :ref:`v2023.2 <releases-v2023.2-minor-changes>`. HTTPS is used by default to communicate with OpenWRT opkg servers.
Original line number Diff line number Diff line
Mesh-VPN
.. _mesh-vpn:

Mesh VPN
========

Gluon integrates several OSI-Layer 2 tunneling protocols to
enable interconnects between local meshes and provide
internetwork access. Available protocols currently are:
Gluon integrates several layer 2 tunneling protocols to
allow connections between local meshes through the internet.

Protocols overview
^^^^^^^^^^^^^^^^^^

For a comprehensive comparison and evaluation of the supported and formerly supported VPN methods that best suit your needs, refer to the following table (Be sure to scroll to the right):

+---------------------------------------+------+----------+----------------+----------------------------+------------------------+------------------+----------------+--------------------------+
| Gluon VPN method                      | IPv4 | IPv6     | Authentication | Encryption                 | Kernelspace forwarding | MTU overhead     | Multithreading | Single interface for all |
|                                       |      |          |                | (no→faster,insecure [1]_)  | (yes→faster)           | (bytes @v4) [7]_ |                | peers                    |
+=======================================+======+==========+================+============================+========================+==================+================+==========================+
| fastd, encrypted                      | yes  | yes      | optional [2]_  | yes                        | no                     | low (98)         | no             | optional                 |
+---------------------------------------+------+----------+----------------+----------------------------+------------------------+------------------+----------------+--------------------------+
| fastd, null                           | yes  | yes      | optional [2]_, | no                         | no                     | low (98)         | no             | optional                 |
|                                       |      |          | partial [3]_   |                            |                        |                  |                |                          |
+---------------------------------------+------+----------+----------------+----------------------------+------------------------+------------------+----------------+--------------------------+
| fastd, ``null@l2tp``, with offloading | yes  | yes      | optional [2]_, | no                         | yes                    | low (82)         |                | optional                 |
|                                       |      |          | partial [3]_   |                            |                        |                  |                |                          |
+---------------------------------------+------+----------+----------------+----------------------------+------------------------+------------------+----------------+--------------------------+
| fastd, ``null@l2tp``, no offloading   | yes  | yes      | optional [2]_, | no                         | no                     | low (82)         | no             | optional                 |
|                                       |      |          | partial [3]_   |                            |                        |                  |                |                          |
+---------------------------------------+------+----------+----------------+----------------------------+------------------------+------------------+----------------+--------------------------+
| Tunneldigger (L2TP - deprecated) [6]_ | yes  | no [4]_  | no             | no                         | yes                    | low (82)         |                | no                       |
+---------------------------------------+------+----------+----------------+----------------------------+------------------------+------------------+----------------+--------------------------+
| WireGuard + VXLAN                     | yes  | yes      | yes            | yes                        | yes                    | high (162)       | yes [5]_       | yes                      |
+---------------------------------------+------+----------+----------------+----------------------------+------------------------+------------------+----------------+--------------------------+

.. [1] No encryption allows internet providers to read and alter mesh traffic.
.. [2] The Gateway can ignore authentication for the initial connection request, via ``"on verify 'true'"``. However, a node→gateway handshake authentication with valid fastd keys in the site.conf is still required.
.. [3] Initial connection request can be authenticated, however, payload data is not authenticated afterward.


.. [4] https://github.com/wlanslovenija/tunneldigger/issues/75
.. [5] https://www.wireguard.com/performance/
.. [6] https://github.com/ffac/community-packages/tree/master/ff-mesh-vpn-tunneldigger
.. [7] :ref:`mtu`

Additional, notable compatibility features
""""""""""""""""""""""""""""""""""""""""""

* fastd: multiple encrypted and unencrypted methods can be handled by one daemon
* fastd: a ``null@l2tp`` peer with offloading is fully compatible with a peer with ``null@l2tp`` without offloading
* fastd+WireGuard: a single secret can be used for both fastd and WireGuard via :ref:`gluon-mesh-vpn-key-translate <gluon-mesh-vpn-key-translate>`, so no need for a node owner switching to (or from) Wireguard from (or to) fastd to submit a new key


Core Protocol handlers
^^^^^^^^^^^^^^^^^^^^^^

- fastd
- L2TPv3 (via tunneldigger)
There are currently two supported protocol handlers which
can be selected as a feature:

fastd is a lightweight userspace tunneling daemon, that
mesh-vpn-fastd
""""""""""""""