"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
hide repositories via gotwebd.conf
To:
gameoftrees@openbsd.org
Date:
Wed, 1 Oct 2025 11:03:18 +0200

Download raw body.

Thread
I would like to add syntax to gotwebd.conf which can be used to
hide repositories.  This will become useful in combination with
another feature I want to add where gotwebd would display contents
of a repository as a static web site. Such repositories could then
be hidden from the regular gotwebd view if desired.


ok?

add gotwebd config parameters for hiding repositories

Add gotwebd.conf parameters which allow repositories to be hidden
from regular gotwebd output. This builds on the per-repository
configuration parameter syntax added for the authentication feature.

M  gotwebd/gotweb.c          |   8+  0-
M  gotwebd/gotwebd.conf.5    |  41+  2-
M  gotwebd/gotwebd.h         |   4+  0-
M  gotwebd/parse.y           |  14+  2-
M  regress/gotsysd/Makefile  |  14+  1-

5 files changed, 81 insertions(+), 5 deletions(-)

commit - 23cefb96ef5b1220ba62581bfdef2e0f8fbcd624
commit + 553231594e207ed9ca25293255c62ff06584463a
blob - 7672772d96f0932203149d91c27b87447771c938
blob + 7f74a54036a708c5ec5bb86222507705111070f1
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -1022,6 +1022,7 @@ gotweb_load_got_path(struct repo_dir **rp, const char 
 	struct gotwebd_repo *repo;
 	enum gotwebd_auth_config auth_config = 0;
 	enum gotwebd_access access = GOTWEBD_ACCESS_DENIED;
+	int repo_is_hidden = 0;
 
 	*rp = calloc(1, sizeof(**rp));
 	if (*rp == NULL)
@@ -1067,6 +1068,7 @@ gotweb_load_got_path(struct repo_dir **rp, const char 
 
 	repo = gotweb_get_repository(srv, repo_dir->name);
 	if (repo) {
+		repo_is_hidden = repo->hidden;
 		auth_config = repo->auth_config;
 		switch (auth_config) {
 		case GOTWEBD_AUTH_DISABLED:
@@ -1084,6 +1086,7 @@ gotweb_load_got_path(struct repo_dir **rp, const char 
 			break;
 		}
 	} else {
+		repo_is_hidden = srv->hide_repositories;
 		auth_config = srv->auth_config;
 		switch (auth_config) {
 		case GOTWEBD_AUTH_DISABLED:
@@ -1109,6 +1112,11 @@ gotweb_load_got_path(struct repo_dir **rp, const char 
 		goto err;
 	}
 
+	if (repo_is_hidden) {
+		error = got_error_path(repo_dir->name, GOT_ERR_NOT_GIT_REPO);
+		goto err;
+	}
+
 	if (srv->respect_exportok &&
 	    faccessat(dirfd(dt), "git-daemon-export-ok", F_OK, 0) == -1) {
 		error = got_error_path(repo_dir->name, GOT_ERR_NOT_GIT_REPO);
blob - e7b1317a646b64b19e51176196a25ed32a93c186
blob + 8ce5a3ead055f07e224ce103c63dba7a3b4c731d
--- gotwebd/gotwebd.conf.5
+++ gotwebd/gotwebd.conf.5
@@ -63,8 +63,11 @@ effectively disables chroot.
 .It Ic disable authentication
 Disable authentication, allowing any browser to view any repository
 not hidden via the
+.Ic hide repositories ,
+.Ic hide repository ,
+or
 .Ic respect_exportok
-directive.
+directives.
 Authentication is disabled by default.
 .It Ic enable authentication Oo Ic insecure Oc
 Enable authentication, requiring browsers to present a login token cookie
@@ -197,8 +200,11 @@ will attempt to fetch it.
 .It Ic disable authentication
 Disable authentication for this server, allowing any browser to view any
 repository not hidden via the
+.Ic hide repositories ,
+.Ic hide repository ,
+or
 .Ic respect_exportok
-directive.
+directives.
 Authentication can also configured on a per-repository basis.
 .Pp
 If not specified, the global configuration context determines
@@ -210,6 +216,29 @@ Authentication can also configured on a per-repository
 .Pp
 If not specified, the global configuration context determines
 whether authentication is enabled.
+.It Ic hide repositories Ar on | off
+Controls whether repositories are hidden by default.
+Hidden repositories cannot be browsed via
+.Xr gotwebd 8 .
+.Pp
+By default,
+.Ic hide repositories
+is set to
+.Ar off
+and all repositories found in the
+.Ic repos_path
+will be displayed.
+.Pp
+If
+.Ic hide repositories
+is set to
+.Ar on
+then a repository will only be displayed if its repository-specific
+.Ic hide repository
+parameter is set to
+.Ar off .
+Repositories will be hidden regardless of whether authentication is
+enabled and has failed or succeeded.
 .It Ic logo_url Ar url
 Set a hyperlink for the logo.
 Defaults to
@@ -302,6 +331,16 @@ before read-only repository access is granted.
 .Pp
 If not specified, the server context or global context determines
 whether authentication is enabled.
+.It Ic hide repository Ar on | off
+Controls whether the repository is hidden.
+Hidden repositories cannot be browsed via
+.Xr gotwebd 8 .
+.Pp
+If not set, the server context's
+.Ic hide repositories
+parameter determines whether
+.Xr gotwebd 8
+will display the repository.
 .El
 .It Ic respect_exportok Ar on | off
 Set whether to display the repository only if it contains the magic
blob - c76a5ca79f14d2b7d419a48d691c48d7af92deae
blob + a0e78241ebfc49bb61c5cdd66999b139d270245f
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
@@ -81,6 +81,7 @@
 #define D_SHOWDESC		 1
 #define D_SHOWURL		 1
 #define D_RESPECTEXPORTOK	 0
+#define D_HIDE_REPOSITORIES	 0
 #define D_MAXREPODISP		 25
 #define D_MAXSLCOMMDISP		 10
 #define D_MAXCOMMITDISP		 25
@@ -384,6 +385,8 @@ struct gotwebd_repo {
 
 	enum gotwebd_auth_config	auth_config;
 	struct gotwebd_access_rule_list access_rules;
+
+	int				hidden;
 };
 TAILQ_HEAD(gotwebd_repolist, gotwebd_repo);
 
@@ -411,6 +414,7 @@ struct server {
 	int		 show_repo_description;
 	int		 show_repo_cloneurl;
 	int		 respect_exportok;
+	int		 hide_repositories;
 
 	enum gotwebd_auth_config auth_config;
 	struct gotwebd_access_rule_list access_rules;
blob - 263ed7737f43df5c22385cc699bb42c5cc0f837e
blob + 36f7355865c10eef10094f25ce0d544c4b6a2a5d
--- gotwebd/parse.y
+++ gotwebd/parse.y
@@ -126,7 +126,7 @@ typedef struct {
 %token	SHOW_SITE_OWNER SHOW_REPO_CLONEURL PORT PREFORK RESPECT_EXPORTOK
 %token	SERVER CHROOT CUSTOM_CSS SOCKET
 %token	SUMMARY_COMMITS_DISPLAY SUMMARY_TAGS_DISPLAY USER AUTHENTICATION
-%token	ENABLE DISABLE INSECURE REPOSITORY PERMIT DENY
+%token	ENABLE DISABLE INSECURE REPOSITORY REPOSITORIES PERMIT DENY HIDE
 
 %token	<v.string>	STRING
 %token	<v.number>	NUMBER
@@ -446,6 +446,9 @@ serveropts1	: REPOS_PATH STRING {
 		| RESPECT_EXPORTOK boolean {
 			new_srv->respect_exportok = $2;
 		}
+		| HIDE REPOSITORIES boolean {
+			new_srv->hide_repositories = $3;
+		}
 		| MAX_REPOS_DISPLAY NUMBER {
 			if ($2 < 0) {
 				yyerror("max_repos_display is too small: %lld",
@@ -578,6 +581,9 @@ repoopts1	: DISABLE AUTHENTICATION {
 			conf_new_access_rule(&new_repo->access_rules,
 			    GOTWEBD_ACCESS_DENIED, $2);
 		}
+		| HIDE REPOSITORY boolean {
+			new_repo->hidden = $3;
+		}
 		;
 
 nl		: '\n' optnl
@@ -627,6 +633,7 @@ lookup(char *s)
 		{ "deny",			DENY },
 		{ "disable",			DISABLE },
 		{ "enable",			ENABLE },
+		{ "hide",			HIDE },
 		{ "insecure",			INSECURE },
 		{ "listen",			LISTEN },
 		{ "login",			GOTWEBD_LOGIN },
@@ -639,6 +646,7 @@ lookup(char *s)
 		{ "port",			PORT },
 		{ "prefork",			PREFORK },
 		{ "repos_path",			REPOS_PATH },
+		{ "repositories",		REPOSITORIES },
 		{ "repository",			REPOSITORY },
 		{ "respect_exportok",		RESPECT_EXPORTOK },
 		{ "server",			SERVER },
@@ -1075,13 +1083,15 @@ parse_config(const char *filename, struct gotwebd *env
 		break;
 	}
 
-	/* Inherit implicit authentication config from parent scope. */
+	/* Inherit implicit authentication/hidden config from parent scope. */
 	TAILQ_FOREACH(srv, &env->servers, entry) {
 		if (srv->auth_config == 0)
 			srv->auth_config = env->auth_config;
 		TAILQ_FOREACH(repo, &srv->repos, entry) {
 			if (repo->auth_config == 0)
 				repo->auth_config = srv->auth_config;
+			if (repo->hidden == -1)
+				repo->hidden = srv->hide_repositories;
 		}
 	}
 
@@ -1137,6 +1147,7 @@ conf_new_server(const char *name)
 	srv->show_repo_description = D_SHOWDESC;
 	srv->show_repo_cloneurl = D_SHOWURL;
 	srv->respect_exportok = D_RESPECTEXPORTOK;
+	srv->hide_repositories = D_HIDE_REPOSITORIES;
 
 	srv->max_repos_display = D_MAXREPODISP;
 	srv->max_commits_display = D_MAXCOMMITDISP;
@@ -1384,6 +1395,7 @@ conf_new_repo(struct server *server, const char *name)
 	if (repo == NULL)
 		fatal("gotwebd_new_repo");
 
+	repo->hidden = -1;
 	TAILQ_INSERT_TAIL(&server->repos, repo, entry);
 
 	return repo;
blob - 0288429b6a3516ebb9f8175cc88833ffe4fe0bff
blob + f36eb4030168acdde61eda535b99ef8652b9d22f
--- regress/gotsysd/Makefile
+++ regress/gotsysd/Makefile
@@ -228,21 +228,32 @@ $(GOTWEBD_CONF):
 	@${UNPRIV} 'echo deny ${GOTSYSD_DEV_USER} >> $@'
 	@${UNPRIV} 'echo server \"VMIP\" { >> $@'
 	@${UNPRIV} 'echo \ \ repos_path \"/git\" >> $@'
+	@${UNPRIV} 'echo \ \ hide repositories on >> $@'
 	@${UNPRIV} 'echo \ \ show_repo_age off >> $@'
 	@${UNPRIV} 'echo \ \ show_repo_description off >> $@'
 	@${UNPRIV} 'echo \ \ show_repo_owner off >> $@'
 	@${UNPRIV} 'echo \ \ show_site_owner off >> $@'
 	@${UNPRIV} 'echo \ \ repository \"public\" { >> $@'
 	@${UNPRIV} 'echo \ \ \ \ disable authentication >> $@'
+	@${UNPRIV} 'echo \ \ \ \ hide repository off >> $@'
 	@${UNPRIV} 'echo \ \ } >> $@'
 	@${UNPRIV} 'echo \ \ repository \"gotdev\" { >> $@'
 	@${UNPRIV} 'echo \ \ \ \ permit ${GOTSYSD_DEV_USER} >> $@'
 	@${UNPRIV} 'echo \ \ \ \ deny ${GOTSYSD_TEST_USER} >> $@'
+	@${UNPRIV} 'echo \ \ \ \ hide repository off >> $@'
 	@${UNPRIV} 'echo \ \ } >> $@'
 	@${UNPRIV} 'echo \ \ repository \"gottest\" { >> $@'
 	@${UNPRIV} 'echo \ \ \ \ permit ${GOTSYSD_TEST_USER} >> $@'
 	@${UNPRIV} 'echo \ \ \ \ deny ${GOTSYSD_DEV_USER} >> $@'
+	@${UNPRIV} 'echo \ \ \ \ hide repository off >> $@'
 	@${UNPRIV} 'echo \ \ } >> $@'
+	@${UNPRIV} 'echo \ \ repository \"hidden\" { >> $@'
+	@${UNPRIV} 'echo \ \ \ \ permit ${GOTSYSD_TEST_USER} >> $@'
+	@${UNPRIV} 'echo \ \ \ \ deny ${GOTSYSD_DEV_USER} >> $@'
+	@${UNPRIV} 'echo \ \ } >> $@'
+	@${UNPRIV} 'echo \ \ repository \"gotsys\" { >> $@'
+	@${UNPRIV} 'echo \ \ \ \ hide repository off >> $@'
+	@${UNPRIV} 'echo \ \ } >> $@'
 	@${UNPRIV} 'echo } >> $@'
 
 build_got:
@@ -341,9 +352,11 @@ test_gotwebd: 
 	VMIP="100.64.$$VMID.3"; \
 	GWIP="100.64.$$VMID.2"; \
 	${UNPRIV} "${GOTSYSD_SSH_CMD} root@$${VMIP} \
-		'rm -rf /git/gotsys.git /git/foo.git /tmp/gotsys'"; \
+		'rm -rf /git/${GOTSYS_REPO} /git/{foo,hidden}.git /tmp/gotsys'"; \
 	${UNPRIV} "${GOTSYSD_SSH_CMD} root@$${VMIP} \
 		got init /git/${GOTSYS_REPO}"; \
+	${UNPRIV} "${GOTSYSD_SSH_CMD} root@$${VMIP} \
+		got init /git/hidden.git"; \
 	${UNPRIV} "${GOTSYSD_SCP_CMD} \
 		${GOT_CONF} root@$${VMIP}:/git/${GOTSYS_REPO}/got.conf"; \
 	${UNPRIV} "${GOTSYSD_SSH_CMD} root@$${VMIP} mkdir /tmp/gotsys "; \