Compare commits

...

10 commits

11 changed files with 336 additions and 27 deletions

View file

@ -11,7 +11,7 @@
time.timeZone = "America/New_York"; time.timeZone = "America/New_York";
networking.hostName = "toki-rpi5"; networking.hostName = "toki-aether";
networking.wireless.iwd.enable = true; networking.wireless.iwd.enable = true;
networking.wireless.iwd.settings = { networking.wireless.iwd.settings = {
Settings.AutoConnect = true; Settings.AutoConnect = true;
@ -27,7 +27,7 @@
users.mutableUsers = false; users.mutableUsers = false;
users.users.root = { users.users.root = {
hashedPassword = "$y$j9T$bEfEX118OZZ58ypi4/D4F/$c1yDUO7hW7WnD5eGj..ZXieELAwUoSPHL4DIsDl6T.6"; hashedPassword = "$y$j9T$bEfEX118OZZ58ypi4/D4F/$c1yDUO7hW7WnD5eGj..ZXieELAwUoSPHL4DIsDl6T.6";
openssh.authorizedKeys.keyFiles = [ ./ssh/authorized_keys ]; openssh.authorizedKeys.keys = [ (import secrets/secrets.nix).publicKey ];
}; };
networking.firewall.allowedTCPPorts = [ 22 80 443 ]; networking.firewall.allowedTCPPorts = [ 22 80 443 ];

View file

@ -1,5 +1,28 @@
{ {
"nodes": { "nodes": {
"agenix": {
"inputs": {
"darwin": [],
"home-manager": "home-manager",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems"
},
"locked": {
"lastModified": 1722339003,
"narHash": "sha256-ZeS51uJI30ehNkcZ4uKqT4ZDARPyqrHADSKAwv5vVCU=",
"owner": "ryantm",
"repo": "agenix",
"rev": "3f1dae074a12feb7327b4bf43cbac0d124488bb7",
"type": "github"
},
"original": {
"owner": "ryantm",
"repo": "agenix",
"type": "github"
}
},
"flake-compat": { "flake-compat": {
"locked": { "locked": {
"lastModified": 1696426674, "lastModified": 1696426674,
@ -14,13 +37,34 @@
"url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
} }
}, },
"home-manager": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1703113217,
"narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1720957393, "lastModified": 1722421184,
"narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=", "narHash": "sha256-/DJBI6trCeVnasdjUo9pbnodCLZcFqnVZiLUfqLH4jA=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "693bc46d169f5af9c992095736e82c3488bf7dbb", "rev": "9f918d616c5321ad374ae6cb5ea89c9e04bf3e58",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -32,6 +76,7 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"agenix": "agenix",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"rpi5-kernel": "rpi5-kernel" "rpi5-kernel": "rpi5-kernel"
} }
@ -56,6 +101,21 @@
"repo": "nix-rpi5", "repo": "nix-rpi5",
"type": "gitlab" "type": "gitlab"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -6,17 +6,23 @@ inputs = {
rpi5-kernel.url = "gitlab:vriska/nix-rpi5"; rpi5-kernel.url = "gitlab:vriska/nix-rpi5";
rpi5-kernel.inputs.nixpkgs.follows = "nixpkgs"; rpi5-kernel.inputs.nixpkgs.follows = "nixpkgs";
agenix.url = "github:ryantm/agenix";
agenix.inputs.nixpkgs.follows = "nixpkgs";
agenix.inputs.darwin.follows = "";
}; };
outputs = inputs@{ self, nixpkgs, rpi5-kernel, ... }: outputs = inputs@{ self, nixpkgs, agenix, ... }:
{ {
nixosConfigurations."toki-rpi5" = nixosConfigurations."toki-aether" =
nixpkgs.lib.nixosSystem { nixpkgs.lib.nixosSystem {
system = "aarch64-linux"; system = "aarch64-linux";
modules = [ modules = [
{ _module.args = inputs; } { _module.args = inputs; }
agenix.nixosModules.default
./config.nix ./config.nix
]; ];
}; };
nixosConfigurations.default = self.nixosConfigurations."toki-aether";
}; };
} }

View file

@ -1,9 +1,5 @@
{ ... }: { ... }:
{ {
security.acme.acceptTerms = true; security.acme.acceptTerms = true;
security.acme.defaults = { security.acme.defaults.email = "kiana.a.sheibani@gmail.com";
email = "kiana.a.sheibani@gmail.com";
dnsProvider = "namecheap";
environmentFile = "/root/.namecheap_api";
};
} }

View file

@ -4,6 +4,5 @@
./acme.nix ./acme.nix
./fail2ban.nix ./fail2ban.nix
./forgejo.nix ./forgejo.nix
./nginx.nix
]; ];
} }

View file

@ -0,0 +1,200 @@
{{$notificationUnreadCount := 0}}
{{if and .IsSigned .NotificationUnreadCount}}
{{$notificationUnreadCount = call .NotificationUnreadCount}}
{{end}}
<nav id="navbar" aria-label="{{ctx.Locale.Tr "aria.navbar"}}">
<div class="navbar-left ui secondary menu">
<!-- the logo -->
<a class="item" id="navbar-logo" href="{{AppSubUrl}}/" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}">
<img width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true">
</a>
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
<div class="ui secondary menu item navbar-mobile-right only-mobile">
{{if .IsSigned}}
<a id="mobile-notifications-icon" class="item tw-w-auto tw-p-2" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}">
<div class="tw-relative">
{{svg "octicon-bell"}}
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
</div>
</a>
{{end}}
<button class="item tw-w-auto ui icon mini button tw-p-2 tw-m-0" id="navbar-expand-toggle" aria-label="{{ctx.Locale.Tr "toggle_menu"}}">{{svg "octicon-three-bars"}}</button>
</div>
<!-- navbar links non-mobile -->
{{if and .IsSigned .MustChangePassword}}
{{/* No links */}}
{{else if .IsSigned}}
{{if not .UnitIssuesGlobalDisabled}}
<a class="item{{if .PageIsIssues}} active{{end}}" href="{{AppSubUrl}}/issues">{{ctx.Locale.Tr "issues"}}</a>
{{end}}
{{if not .UnitPullsGlobalDisabled}}
<a class="item{{if .PageIsPulls}} active{{end}}" href="{{AppSubUrl}}/pulls">{{ctx.Locale.Tr "pull_requests"}}</a>
{{end}}
{{if not (and .UnitIssuesGlobalDisabled .UnitPullsGlobalDisabled)}}
{{if .ShowMilestonesDashboardPage}}
<a class="item{{if .PageIsMilestonesDashboard}} active{{end}}" href="{{AppSubUrl}}/milestones">{{ctx.Locale.Tr "milestones"}}</a>
{{end}}
{{end}}
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a>
{{else if .IsLandingPageOrganizations}}
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{ctx.Locale.Tr "explore"}}</a>
{{else}}
<a class="item{{if .PageIsUserProfile}} active{{end}}" href="{{AppSubUrl}}/toki">My Profile</a>
<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{ctx.Locale.Tr "explore"}}</a>
{{end}}
</div>
<!-- the full dropdown menus -->
<div class="navbar-right ui secondary menu">
{{if and .IsSigned .MustChangePassword}}
<div class="ui dropdown jump item" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
<span class="text tw-flex tw-items-center">
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
<span class="only-mobile tw-ml-2">{{.SignedUser.Name}}</span>
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
</span>
<div class="menu user-menu">
<div class="ui header">
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
</div>
<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
{{svg "octicon-sign-out"}}
{{ctx.Locale.Tr "sign_out"}}
</a>
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
{{else if .IsSigned}}
{{if EnableTimetracking}}
<a class="active-stopwatch-trigger item tw-mx-0{{if not .ActiveStopwatch}} tw-hidden{{end}}" href="{{.ActiveStopwatch.IssueLink}}" title="{{ctx.Locale.Tr "active_stopwatch"}}">
<div class="tw-relative">
{{svg "octicon-stopwatch"}}
<span class="header-stopwatch-dot"></span>
</div>
<span class="only-mobile tw-ml-2">{{ctx.Locale.Tr "active_stopwatch"}}</span>
</a>
<div class="active-stopwatch-popup item tippy-target tw-p-2">
<div class="tw-flex tw-items-center">
<a class="stopwatch-link tw-flex tw-items-center" href="{{.ActiveStopwatch.IssueLink}}">
{{svg "octicon-issue-opened" 16 "tw-mr-2"}}
<span class="stopwatch-issue">{{.ActiveStopwatch.RepoSlug}}#{{.ActiveStopwatch.IssueIndex}}</span>
<span class="ui primary label stopwatch-time tw-my-0 tw-mx-4" data-seconds="{{.ActiveStopwatch.Seconds}}">
{{if .ActiveStopwatch}}{{Sec2Time .ActiveStopwatch.Seconds}}{{end}}
</span>
</a>
<form class="stopwatch-commit" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/toggle">
{{.CsrfTokenHtml}}
<button
type="submit"
class="ui button mini compact basic icon"
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.stop_tracking"}}"
>{{svg "octicon-square-fill"}}</button>
</form>
<form class="stopwatch-cancel" method="post" action="{{.ActiveStopwatch.IssueLink}}/times/stopwatch/cancel">
{{.CsrfTokenHtml}}
<button
type="submit"
class="ui button mini compact basic icon"
data-tooltip-content="{{ctx.Locale.Tr "repo.issues.cancel_tracking"}}"
>{{svg "octicon-trash"}}</button>
</form>
</div>
</div>
{{end}}
<a class="item not-mobile tw-mx-0" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{ctx.Locale.Tr "notifications"}}" aria-label="{{ctx.Locale.Tr "notifications"}}">
<div class="tw-relative">
{{svg "octicon-bell"}}
<span class="notification_count{{if not $notificationUnreadCount}} tw-hidden{{end}}">{{$notificationUnreadCount}}</span>
</div>
</a>
<div class="ui dropdown jump item tw-mx-0 tw-pr-2" data-tooltip-content="{{ctx.Locale.Tr "create_new"}}">
<span class="text">
{{svg "octicon-plus"}}
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
<span class="only-mobile">{{ctx.Locale.Tr "create_new"}}</span>
</span>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/repo/create">
{{svg "octicon-plus"}} {{ctx.Locale.Tr "new_repo"}}
</a>
{{if not .DisableMigrations}}
<a class="item" href="{{AppSubUrl}}/repo/migrate">
{{svg "octicon-repo-push"}} {{ctx.Locale.Tr "new_migrate"}}
</a>
{{end}}
{{if .SignedUser.CanCreateOrganization}}
<a class="item" href="{{AppSubUrl}}/org/create">
{{svg "octicon-organization"}} {{ctx.Locale.Tr "new_org"}}
</a>
{{end}}
</div><!-- end content create new menu -->
</div><!-- end dropdown menu create new -->
<div class="ui dropdown jump item tw-mx-0 tw-pr-2" data-tooltip-content="{{ctx.Locale.Tr "user_profile_and_more"}}">
<span class="text tw-flex tw-items-center">
{{ctx.AvatarUtils.Avatar .SignedUser 24 "tw-mr-1"}}
<span class="only-mobile tw-ml-2">{{.SignedUser.Name}}</span>
<span class="not-mobile">{{svg "octicon-triangle-down"}}</span>
</span>
<div class="menu user-menu">
<div class="ui header">
{{ctx.Locale.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong>
</div>
<div class="divider"></div>
<a class="item" href="{{.SignedUser.HomeLink}}">
{{svg "octicon-person"}}
{{ctx.Locale.Tr "your_profile"}}
</a>
{{if not .DisableStars}}
<a class="item" href="{{.SignedUser.HomeLink}}?tab=stars">
{{svg "octicon-star"}}
{{ctx.Locale.Tr "your_starred"}}
</a>
{{end}}
<a class="item" href="{{AppSubUrl}}/notifications/subscriptions">
{{svg "octicon-bell"}}
{{ctx.Locale.Tr "notification.subscriptions"}}
</a>
<a class="{{if .PageIsUserSettings}}active {{end}}item" href="{{AppSubUrl}}/user/settings">
{{svg "octicon-tools"}}
{{ctx.Locale.Tr "your_settings"}}
</a>
<a class="item" target="_blank" rel="noopener noreferrer" href="https://forgejo.org/docs/latest/">
{{svg "octicon-question"}}
{{ctx.Locale.Tr "help"}}
</a>
{{if .IsAdmin}}
<div class="divider"></div>
<a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/admin">
{{svg "octicon-server"}}
{{ctx.Locale.Tr "admin_panel"}}
</a>
{{end}}
<div class="divider"></div>
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout">
{{svg "octicon-sign-out"}}
{{ctx.Locale.Tr "sign_out"}}
</a>
</div><!-- end content avatar menu -->
</div><!-- end dropdown avatar menu -->
{{else}}
{{if .ShowRegistrationButton}}
<a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up">
{{svg "octicon-person"}} {{ctx.Locale.Tr "register"}}
</a>
{{end}}
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login{{if not .PageIsSignIn}}?redirect_to={{.CurrentURL}}{{end}}">
{{svg "octicon-sign-in"}} &nbsp; {{ctx.Locale.Tr "sign_in"}}
</a>
{{end}}
</div><!-- end full right menu -->
</nav>

View file

@ -0,0 +1,13 @@
{{template "base/head" .}}
<div role="main" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home"}}{{end}}" class="page-content home">
<div class="tw-px-8" style="margin-top: 4rem;">
<div class="center">
<div class="hero tw-mb-8">
<h2 class="ui icon header title">Toki's personal code forge</h2>
<h3>Powered by <a href="https://forgejo.org/">Forgejo</a>, a painless, self-hosted Git service.</h3>
</div>
<img class="logo" width="80" height="80" src="{{AssetUrlPrefix}}/img/logo.svg" alt="Forgejo">
</div>
</div>
</div>
{{template "base/footer" .}}

View file

@ -3,6 +3,7 @@ let
cfg = config.services.forgejo; cfg = config.services.forgejo;
srv = cfg.settings.server; srv = cfg.settings.server;
in { in {
services.nginx.enable = true;
services.nginx.virtualHosts.${srv.DOMAIN} = { services.nginx.virtualHosts.${srv.DOMAIN} = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
@ -14,34 +15,59 @@ in {
services.forgejo = { services.forgejo = {
enable = true; enable = true;
user = "git";
group = cfg.user;
database.user = cfg.user;
settings = { settings = {
DEFAULT.APP_NAME = "Code by toki!";
server = { server = {
DOMAIN = "git.tokinanpa.dev"; DOMAIN = "git.tokinanpa.dev";
ROOT_URL = "https://${srv.DOMAIN}/"; ROOT_URL = "https://${srv.DOMAIN}/";
}; };
service = { service.DISABLE_REGISTRATION = true;
DISABLE_REGISTRATION = true;
};
repository = { repository = {
DEFAULT_REPO_UNITS = "repo.code,repo.releases,repo.issues"; DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
DISABLE_STARS = true;
ENABLE_PUSH_CREATE_USER = true; ENABLE_PUSH_CREATE_USER = true;
DEFAULT_PUSH_CREATE_PRIVATE = false; DEFAULT_PUSH_CREATE_PRIVATE = false;
PREFERRED_LICENSES = "MIT"; PREFERRED_LICENSES = "MIT,GPL-3.0-or-later";
};
mirror.DEFAULT_INTERVAL = "1h";
indexer = {
REPO_INDEXER_ENABLED = true;
REPO_INDEXER_EXCLUDE = "**.pdf, **.png, **.jpg, **.jpeg, **.svg, **.web, **.gpg, **.age";
}; };
ui = { ui = {
DEFAULT_THEME = "forgejo-dark"; DEFAULT_THEME = "forgejo-dark";
DEFAULT_SHOW_FULL_NAME = true; GRAPH_MAX_COMMIT_NUM = 250;
}; };
"ui.meta" = {
AUTHOR = "Kiana Sheibani";
DESCRIPTION = "Code by toki! Powered by Forgejo";
KEYWORDS = "git,forge,forgejo,toki,tokinanpa";
};
"service.explore".DISABLE_USERS_PAGE = true;
mirror.DEFAULT_INTERVAL = "1h"; federation.ENABLED = true;
}; };
}; };
systemd.tmpfiles.rules = [
"L+ ${cfg.stateDir}/custom/templates - - - - ${./forgejo-templates}"
];
users.users.${cfg.user} = {
home = cfg.stateDir;
useDefaultShell = true;
group = cfg.group;
isSystemUser = true;
};
users.groups.${cfg.group} = {};
} }

View file

@ -1,4 +0,0 @@
{ ... }:
{
services.nginx.enable = true;
}

14
secrets/secrets.nix Normal file
View file

@ -0,0 +1,14 @@
let
publicKey =
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDemOeWGP40M495KAuylZfRHXKKr9av0QH" +
"YjQwuG5EKzoy+KH0EAtBM3MbDLX5+bCd4O4oB9H/ZWxDZFfaitTPf1nrBMA89GWAxiGwVT3" +
"U2kQL2KUIP9rXjH/KLwocqnqsljRka1McF0mijtpMhNR0jpXAOfZboHFWRE07kRacvXmhkl" +
"tcJhXiCGMYmUfFT/HroxSgV+1BM9csYItzHlHFhoB2laEQOoTE5jLxkTkqZ55W0V9QUlM1N" +
"830fvhv9z/I6PQcIPXttB4nm+339r2qA3qncRkF7j0+JIXbUkIxK7nQhv25EyFUS8WplnI7" +
"mbb2T9JWVeLsAO24WrAApbPxmu+ItKq003Qi4a/0+v6D2PCXm+YoxJlM5aHh8FZdXoIhMv7" +
"6j3lk0P0sN9Sr09gjoWkV+/rSN+3ZLCJBGS5a3LpBk3HC2ZP/mvfsd1LTDhYQBJSW0LiBZO" +
"5aRuKZrTbyY9+i75cTWjnJuvZyBDn3giSYMiVhIAcZg5dU0ySG4M28= kiana@kiana-laptop";
in
{
inherit publicKey;
}

View file

@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDemOeWGP40M495KAuylZfRHXKKr9av0QHYjQwuG5EKzoy+KH0EAtBM3MbDLX5+bCd4O4oB9H/ZWxDZFfaitTPf1nrBMA89GWAxiGwVT3U2kQL2KUIP9rXjH/KLwocqnqsljRka1McF0mijtpMhNR0jpXAOfZboHFWRE07kRacvXmhkltcJhXiCGMYmUfFT/HroxSgV+1BM9csYItzHlHFhoB2laEQOoTE5jLxkTkqZ55W0V9QUlM1N830fvhv9z/I6PQcIPXttB4nm+339r2qA3qncRkF7j0+JIXbUkIxK7nQhv25EyFUS8WplnI7mbb2T9JWVeLsAO24WrAApbPxmu+ItKq003Qi4a/0+v6D2PCXm+YoxJlM5aHh8FZdXoIhMv76j3lk0P0sN9Sr09gjoWkV+/rSN+3ZLCJBGS5a3LpBk3HC2ZP/mvfsd1LTDhYQBJSW0LiBZO5aRuKZrTbyY9+i75cTWjnJuvZyBDn3giSYMiVhIAcZg5dU0ySG4M28= kiana@kiana-laptop