Skip to content

Commit 33b5656

Browse files
authored
Merge branch 'main' into feature/clear-merge-commit-content-button
2 parents a9d0d90 + 43aafc5 commit 33b5656

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1785
-248
lines changed

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,13 @@ The following configuration set `Content-Type: application/vnd.android.package-a
289289
This includes CSS files, images, JS files and web fonts.
290290
Avatar images are dynamic resources and still served by Gitea.
291291
The option can be just a different path, as in `/static`, or another domain, as in `https://cdn.example.com`.
292-
Requests are then made as `%(ROOT_URL)s/static/css/index.css` and `https://cdn.example.com/css/index.css` respective.
292+
Requests are then made as `%(ROOT_URL)s/static/assets/css/index.css` or `https://cdn.example.com/assets/css/index.css` respectively.
293293
The static files are located in the `public/` directory of the Gitea source repository.
294+
You can proxy the STATIC_URL_PREFIX requests to Gitea server to serve the static
295+
assets, or copy the manually built Gitea assets from `$GITEA_BUILD/public` to
296+
the assets location, eg: `/var/www/assets`, make sure `$STATIC_URL_PREFIX/assets/css/index.css`
297+
points to `/var/www/assets/css/index.css`.
298+
294299
- `HTTP_ADDR`: **0.0.0.0**: HTTP listen address.
295300
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket
296301
defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.

docs/content/doc/features/authentication.en-us.md

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,47 @@ Uses the following fields:
166166

167167
## PAM (Pluggable Authentication Module)
168168

169-
To configure PAM, set the 'PAM Service Name' to a filename in `/etc/pam.d/`. To
170-
work with normal Linux passwords, the user running Gitea must have read access
171-
to `/etc/shadow`.
172-
173-
**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build), and the official binaries provided do not have this enabled.
169+
This procedure enables PAM authentication. Users may still be added to the
170+
system manually using the user administration. PAM provides a mechanism to
171+
automatically add users to the current database by testing them against PAM
172+
authentication. To work with normal Linux passwords, the user running Gitea
173+
must also have read access to `/etc/shadow` in order to check the validity of
174+
the account when logging in using a public key.
175+
176+
**Note**: If a user has added SSH public keys into Gitea, the use of these
177+
keys _may_ bypass the login check system. Therefore, if you wish to disable a user who
178+
authenticates with PAM, you _should_ also manually disable the account in Gitea using the
179+
built-in user manager.
180+
181+
1. Configure and prepare the installation.
182+
- It is recommended that you create an administrative user.
183+
- Deselecting automatic sign-up may also be desired.
184+
1. Once the database has been initialized, log in as the newly created
185+
administrative user.
186+
1. Navigate to the user setting (icon in top-right corner), and select
187+
`Site Administration` -> `Authentication Sources`, and select
188+
`Add Authentication Source`.
189+
1. Fill out the field as follows:
190+
- `Authentication Type` : `PAM`
191+
- `Name` : Any value should be valid here, use "System Authentication" if
192+
you'd like.
193+
- `PAM Service Name` : Select the appropriate file listed under `/etc/pam.d/`
194+
that performs the authentication desired.[^1]
195+
- `PAM Email Domain` : The e-mail suffix to append to user authentication.
196+
For example, if the login system expects a user called `gituser`, and this
197+
field is set to `mail.com`, then Gitea will expect the `user email` field
198+
for an authenticated GIT instance to be `[email protected]`.[^2]
199+
200+
**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build),
201+
and the official binaries provided do not have this enabled. PAM requires that
202+
the necessary libpam dynamic library be available and the necessary PAM
203+
development headers be accessible to the compiler.
204+
205+
[^1]: For example, using standard Linux log-in on Debian "Bullseye" use
206+
`common-session-noninteractive` - this value may be valid for other flavors of
207+
Debian including Ubuntu and Mint, consult your distribution's documentation.
208+
[^2]: **This is a required field for PAM**. Be aware: In the above example, the
209+
user will log into the Gitea web interface as `gituser` and not `[email protected]`
174210

175211
## SMTP (Simple Mail Transfer Protocol)
176212

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
date: "2022-11-01T00:00:00+00:00"
3+
title: "Storage"
4+
slug: "packages/storage"
5+
draft: false
6+
toc: false
7+
menu:
8+
sidebar:
9+
parent: "packages"
10+
name: "storage"
11+
weight: 5
12+
identifier: "storage"
13+
---
14+
15+
# Storage
16+
17+
This document describes the storage of the package registry and how it can be managed.
18+
19+
**Table of Contents**
20+
21+
{{< toc >}}
22+
23+
## Deduplication
24+
25+
The package registry has a build-in deduplication of uploaded blobs.
26+
If two identical files are uploaded only one blob is saved on the filesystem.
27+
This ensures no space is wasted for duplicated files.
28+
29+
If two packages are uploaded with identical files, both packages will display the same size but on the filesystem they require only half of the size.
30+
Whenever a package gets deleted only the references to the underlaying blobs are removed.
31+
The blobs get not removed at this moment, so they still require space on the filesystem.
32+
When a new package gets uploaded the existing blobs may get referenced again.
33+
34+
These unreferenced blobs get deleted by a [clean up job]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#cron---cleanup-expired-packages-croncleanup_packages" >}}).
35+
The config setting `OLDER_THAN` configures how long unreferenced blobs are kept before they get deleted.
36+
37+
## Cleanup Rules
38+
39+
Package registries can become large over time without cleanup.
40+
It's recommended to delete unnecessary packages and set up cleanup rules to automatically manage the package registry usage.
41+
Every package owner (user or organization) manages the cleanup rules which are applied to their packages.
42+
43+
|Setting|Description|
44+
|-|-|
45+
|Enabled|Turn the cleanup rule on or off.|
46+
|Type|Every rule manages a specific package type.|
47+
|Apply pattern to full package name|If enabled, the patterns below are applied to the full package name (`package/version`). Otherwise only the version (`version`) is used.|
48+
|Keep the most recent|How many versions to *always* keep for each package.|
49+
|Keep versions matching|The regex pattern that determines which versions to keep. An empty pattern keeps no version while `.+` keeps all versions. The container registry will always keep the `latest` version even if not configured.|
50+
|Remove versions older than|Remove only versions older than the selected days.|
51+
|Remove versions matching|The regex pattern that determines which versions to remove. An empty pattern or `.+` leads to the removal of every package if no other setting tells otherwise.|
52+
53+
Every cleanup rule can show a preview of the affected packages.
54+
This can be used to check if the cleanup rules is proper configured.
55+
56+
### Regex examples
57+
58+
Regex patterns are automatically surrounded with `\A` and `\z` anchors.
59+
Do not include any `\A`, `\z`, `^` or `$` token in the regex patterns as they are not necessary.
60+
The patterns are case-insensitive which matches the behaviour of the package registry in Gitea.
61+
62+
|Pattern|Description|
63+
|-|-|
64+
|`.*`|Match every possible version.|
65+
|`v.+`|Match versions that start with `v`.|
66+
|`release`|Match only the version `release`.|
67+
|`release.*`|Match versions that are either named or start with `release`.|
68+
|`.+-temp-.+`|Match versions that contain `-temp-`.|
69+
|`v.+\|release`|Match versions that either start with `v` or are named `release`.|
70+
|`package/v.+\|other/release`|Match versions of the package `package` that start with `v` or the version `release` of the package `other`. This needs the setting *Apply pattern to full package name* enabled.|
71+
72+
### How the cleanup rules work
73+
74+
The cleanup rules are part of the [clean up job]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#cron---cleanup-expired-packages-croncleanup_packages" >}}) and run periodicly.
75+
76+
The cleanup rule:
77+
78+
1. Collects all packages of the package type for the owners registry.
79+
1. For every package it collects all versions.
80+
1. Excludes from the list the # versions based on the *Keep the most recent* value.
81+
1. Excludes from the list any versions matching the *Keep versions matching* value.
82+
1. Excludes from the list the versions more recent than the *Remove versions older than* value.
83+
1. Excludes from the list any versions not matching the *Remove versions matching* value.
84+
1. Deletes the remaining versions.

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,8 @@ var migrations = []Migration{
439439
NewMigration("Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText),
440440
// v233 -> v234
441441
NewMigration("Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook),
442+
// v234 -> v235
443+
NewMigration("Add package cleanup rule table", v1_19.CreatePackageCleanupRuleTable),
442444
}
443445

444446
// GetCurrentDBVersion returns the current db version

models/migrations/v1_19/v234.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package v1_19 //nolint
6+
7+
import (
8+
"code.gitea.io/gitea/modules/timeutil"
9+
10+
"xorm.io/xorm"
11+
)
12+
13+
func CreatePackageCleanupRuleTable(x *xorm.Engine) error {
14+
type PackageCleanupRule struct {
15+
ID int64 `xorm:"pk autoincr"`
16+
Enabled bool `xorm:"INDEX NOT NULL DEFAULT false"`
17+
OwnerID int64 `xorm:"UNIQUE(s) INDEX NOT NULL DEFAULT 0"`
18+
Type string `xorm:"UNIQUE(s) INDEX NOT NULL"`
19+
KeepCount int `xorm:"NOT NULL DEFAULT 0"`
20+
KeepPattern string `xorm:"NOT NULL DEFAULT ''"`
21+
RemoveDays int `xorm:"NOT NULL DEFAULT 0"`
22+
RemovePattern string `xorm:"NOT NULL DEFAULT ''"`
23+
MatchFullName bool `xorm:"NOT NULL DEFAULT false"`
24+
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL DEFAULT 0"`
25+
UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL DEFAULT 0"`
26+
}
27+
28+
return x.Sync2(new(PackageCleanupRule))
29+
}

models/packages/package.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,21 @@ const (
4545
TypeVagrant Type = "vagrant"
4646
)
4747

48+
var TypeList = []Type{
49+
TypeComposer,
50+
TypeConan,
51+
TypeContainer,
52+
TypeGeneric,
53+
TypeHelm,
54+
TypeMaven,
55+
TypeNpm,
56+
TypeNuGet,
57+
TypePub,
58+
TypePyPI,
59+
TypeRubyGems,
60+
TypeVagrant,
61+
}
62+
4863
// Name gets the name of the package type
4964
func (pt Type) Name() string {
5065
switch pt {
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package packages
6+
7+
import (
8+
"context"
9+
"errors"
10+
"fmt"
11+
"regexp"
12+
13+
"code.gitea.io/gitea/models/db"
14+
"code.gitea.io/gitea/modules/timeutil"
15+
16+
"xorm.io/builder"
17+
)
18+
19+
var ErrPackageCleanupRuleNotExist = errors.New("Package blob does not exist")
20+
21+
func init() {
22+
db.RegisterModel(new(PackageCleanupRule))
23+
}
24+
25+
// PackageCleanupRule represents a rule which describes when to clean up package versions
26+
type PackageCleanupRule struct {
27+
ID int64 `xorm:"pk autoincr"`
28+
Enabled bool `xorm:"INDEX NOT NULL DEFAULT false"`
29+
OwnerID int64 `xorm:"UNIQUE(s) INDEX NOT NULL DEFAULT 0"`
30+
Type Type `xorm:"UNIQUE(s) INDEX NOT NULL"`
31+
KeepCount int `xorm:"NOT NULL DEFAULT 0"`
32+
KeepPattern string `xorm:"NOT NULL DEFAULT ''"`
33+
KeepPatternMatcher *regexp.Regexp `xorm:"-"`
34+
RemoveDays int `xorm:"NOT NULL DEFAULT 0"`
35+
RemovePattern string `xorm:"NOT NULL DEFAULT ''"`
36+
RemovePatternMatcher *regexp.Regexp `xorm:"-"`
37+
MatchFullName bool `xorm:"NOT NULL DEFAULT false"`
38+
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL DEFAULT 0"`
39+
UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL DEFAULT 0"`
40+
}
41+
42+
func (pcr *PackageCleanupRule) CompiledPattern() error {
43+
if pcr.KeepPatternMatcher != nil || pcr.RemovePatternMatcher != nil {
44+
return nil
45+
}
46+
47+
if pcr.KeepPattern != "" {
48+
var err error
49+
pcr.KeepPatternMatcher, err = regexp.Compile(fmt.Sprintf(`(?i)\A%s\z`, pcr.KeepPattern))
50+
if err != nil {
51+
return err
52+
}
53+
}
54+
55+
if pcr.RemovePattern != "" {
56+
var err error
57+
pcr.RemovePatternMatcher, err = regexp.Compile(fmt.Sprintf(`(?i)\A%s\z`, pcr.RemovePattern))
58+
if err != nil {
59+
return err
60+
}
61+
}
62+
63+
return nil
64+
}
65+
66+
func InsertCleanupRule(ctx context.Context, pcr *PackageCleanupRule) (*PackageCleanupRule, error) {
67+
return pcr, db.Insert(ctx, pcr)
68+
}
69+
70+
func GetCleanupRuleByID(ctx context.Context, id int64) (*PackageCleanupRule, error) {
71+
pcr := &PackageCleanupRule{}
72+
73+
has, err := db.GetEngine(ctx).ID(id).Get(pcr)
74+
if err != nil {
75+
return nil, err
76+
}
77+
if !has {
78+
return nil, ErrPackageCleanupRuleNotExist
79+
}
80+
return pcr, nil
81+
}
82+
83+
func UpdateCleanupRule(ctx context.Context, pcr *PackageCleanupRule) error {
84+
_, err := db.GetEngine(ctx).ID(pcr.ID).AllCols().Update(pcr)
85+
return err
86+
}
87+
88+
func GetCleanupRulesByOwner(ctx context.Context, ownerID int64) ([]*PackageCleanupRule, error) {
89+
pcrs := make([]*PackageCleanupRule, 0, 10)
90+
return pcrs, db.GetEngine(ctx).Where("owner_id = ?", ownerID).Find(&pcrs)
91+
}
92+
93+
func DeleteCleanupRuleByID(ctx context.Context, ruleID int64) error {
94+
_, err := db.GetEngine(ctx).ID(ruleID).Delete(&PackageCleanupRule{})
95+
return err
96+
}
97+
98+
func HasOwnerCleanupRuleForPackageType(ctx context.Context, ownerID int64, packageType Type) (bool, error) {
99+
return db.GetEngine(ctx).
100+
Where("owner_id = ? AND type = ?", ownerID, packageType).
101+
Exist(&PackageCleanupRule{})
102+
}
103+
104+
func IterateEnabledCleanupRules(ctx context.Context, callback func(context.Context, *PackageCleanupRule) error) error {
105+
return db.Iterate(
106+
ctx,
107+
builder.Eq{"enabled": true},
108+
callback,
109+
)
110+
}

models/packages/package_version.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,15 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P
320320
return pvs, count, err
321321
}
322322

323+
// ExistVersion checks if a version matching the search options exist
324+
func ExistVersion(ctx context.Context, opts *PackageSearchOptions) (bool, error) {
325+
return db.GetEngine(ctx).
326+
Where(opts.toConds()).
327+
Table("package_version").
328+
Join("INNER", "package", "package.id = package_version.package_id").
329+
Exist(new(PackageVersion))
330+
}
331+
323332
// CountVersions counts all versions of packages matching the search options
324333
func CountVersions(ctx context.Context, opts *PackageSearchOptions) (int64, error) {
325334
return db.GetEngine(ctx).

0 commit comments

Comments
 (0)