diff --git a/scripts/update-gluon.sh b/scripts/update-gluon.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f014c8c11580990796145d9a4dbf1229af77a345
--- /dev/null
+++ b/scripts/update-gluon.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+set -eu
+
+readonly gluon_remote_upstream=https://github.com/freifunk-gluon/gluon.git
+
+script_path=$(dirname $(readlink -f "$0"))
+gluon_path=$(readlink -f "$script_path/../gluon")
+
+tag_to_update_to="${1:-}"
+
+if [ -z "$tag_to_update_to" ]; then
+	echo "Usage: $0 [tag to update to]"
+	exit 1
+fi
+
+verify_remotes() {
+	remote_upstream=$(git -C "$gluon_path" remote get-url upstream)
+
+	if [ "$remote_upstream" != "$gluon_remote_upstream" ]; then
+		echo "Upstream remote is not set up correctly. Please run:"
+		echo "  git -C \"$gluon_path\" remote set-url upstream \"$gluon_remote_upstream\""
+		exit 1
+	fi
+}
+
+verify_remotes
+
+git -C "$gluon_path" fetch origin --tags
+
+git -C "$gluon_path" fetch upstream "$tag_to_update_to"
+
+current_branch_name=$(git -C "$gluon_path" rev-parse --abbrev-ref HEAD)
+current_upstream_tag_name=${current_branch_name/-ffs/}
+
+git -C "$gluon_path" checkout -b "$tag_to_update_to-ffs"
+
+git -C "$gluon_path" rebase -i "$current_upstream_tag_name" --onto FETCH_HEAD
+
+fork_tagname="$tag_to_update_to-ffs0.1"
+git -C "$gluon_path" tag "$fork_tagname"
+
+git -C "$gluon_path" push origin "$tag_to_update_to"
+git -C "$gluon_path" push origin "$fork_tagname"