Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/.vitepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ export default withMermaid(defineConfig({
text: 'Operations',
items: [
{ text: 'Reverse Proxy', link: '/operations/reverse-proxy' },
{ text: 'Cross Compilation', link: '/operations/cross-compilation' },
{ text: 'Server CLI', link: '/operations/server-cli' },
{ text: 'Import / Export', link: '/operations/import-export' },
{ text: 'Cross Compilation', link: '/operations/cross-compilation' },
],
},
{
Expand Down
4 changes: 2 additions & 2 deletions docs/operations/import-export.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ plikd export /path/to/export.bin
Sample output:

```
Exporting metadata from sqlite3 plik.db to /path/to/export.bin
Exporting metadata from sqlite3 to /path/to/export.bin
exported 3 users
exported 5 tokens
exported 142 uploads
Expand All @@ -38,7 +38,7 @@ plikd import /path/to/export.bin
Sample output:

```
Importing metadata from /path/to/export.bin to postgres host=localhost...
Importing metadata from /path/to/export.bin to postgres
imported 3 out of 3 uploads
imported 287 out of 287 files
imported 3 out of 3 users
Expand Down
155 changes: 155 additions & 0 deletions docs/operations/server-cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Server CLI

The `plikd` binary is both the Plik server and an admin CLI for managing users, tokens, uploads, and maintenance tasks.

::: tip
All `plikd` commands load configuration using the same search order:
`--config` flag → `PLIKD_CONFIG` env → `./plikd.cfg` → `/etc/plikd.cfg`
:::

## User Management

Manage user accounts (local, Google, OVH, OIDC providers).

### Create a user

```bash
# Local user with password
plikd user create --login admin --password s3cret123 --admin

# OAuth provider user
plikd user create --provider google --login user@gmail.com --name "John Doe"

# With size and TTL limits
plikd user create --login bob --max-file-size 100MB --max-user-size 1GB --max-ttl 7d
```

| Flag | Description |
|------|-------------|
| `--provider` | Auth provider: `local` (default), `google`, `ovh`, `oidc` |
| `--login` | User login (min 4 chars) |
| `--password` | Password for local users (min 8 chars, auto-generated if omitted) |
| `--name` | Display name |
| `--email` | Email address |
| `--admin` | Grant admin privileges |
| `--max-file-size` | Per-file size limit (e.g. `100MB`, `-1` for unlimited) |
| `--max-user-size` | Total storage limit (e.g. `1GB`, `-1` for unlimited) |
| `--max-ttl` | Maximum upload TTL (e.g. `7d`, `24h`) |

### List users

```bash
plikd user list
```

### Show user details

```bash
plikd user show --login admin
plikd user show --provider google --login user@gmail.com
```

### Update a user

```bash
plikd user update --login admin --admin
plikd user update --login bob --max-file-size 500MB --max-ttl 14d
```

Only the specified flags are changed — all other fields are preserved.

### Delete a user

```bash
plikd user delete --login admin
plikd user delete --provider google --login user@gmail.com
```

::: warning
Deleting a user also removes **all their uploads and files** from both the metadata and data backends.
:::

## Token Management

Manage API tokens for authenticated uploads.

### Create a token

```bash
plikd token create --login admin --comment "CI/CD pipeline"
```

| Flag | Description |
|------|-------------|
| `--provider` | Auth provider (default: `local`) |
| `--login` | User login to create the token for |
| `--comment` | Token description |

### List tokens

```bash
plikd token list
```

### Delete a token

```bash
plikd token delete --token xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```

## File & Upload Management

Manage uploads and individual files in the system.

### List files

```bash
# List all files
plikd file list

# List files in a specific upload
plikd file list --upload abc123

# Show a specific file
plikd file list --file def456

# Machine-readable sizes (bytes)
plikd file list --human=false
```

### Show file details

```bash
plikd file show --file abc123
```

Displays full file metadata, upload URL, and direct download URL.

### Delete

You must specify exactly one of `--file`, `--upload`, or `--all`:

```bash
# Delete a single file
plikd file delete --file abc123

# Delete an entire upload
plikd file delete --upload def456

# Delete ALL uploads (requires confirmation)
plikd file delete --all
```

::: danger
`--all` removes **every upload** in the system. A confirmation prompt is always shown.
:::

## Cleanup

Remove expired uploads and purge deleted files from the data backend:

```bash
plikd clean
```

This runs the same cleanup routine that the server executes periodically when running. Use it for manual maintenance or cron jobs.
8 changes: 4 additions & 4 deletions server/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ The server binary `plikd` uses [cobra](https://github.com/spf13/cobra) for CLI m
| File | Command | Description |
|------|---------|-------------|
| `root.go` | `plikd` | Start the server (default command) |
| `user.go` | `plikd user create/list/delete` | Manage local users |
| `user.go` | `plikd user create/show/update/list/delete` | Manage users |
| `token.go` | `plikd token create/list/delete` | Manage user tokens |
| `file.go` | `plikd file list/delete` | Manage uploads/files |
| `file.go` | `plikd file list/show/delete` | Manage uploads/files (`delete` requires `--file`, `--upload`, or `--all`) |
| `clean.go` | `plikd clean` | Run metadata cleanup |
| `import.go` | `plikd import` | Import metadata from gob + Snappy binary |
| `export.go` | `plikd export` | Export metadata to gob + Snappy binary |
| `import.go` | `plikd import [input-file]` | Import metadata from gob + Snappy binary |
| `export.go` | `plikd export [output-file]` | Export metadata to gob + Snappy binary |

Config loading order: `--config` flag → `PLIKD_CONFIG` env → `./plikd.cfg` → `/etc/plikd.cfg`.

Expand Down
4 changes: 4 additions & 0 deletions server/cmd/clean.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"

"github.com/root-gg/plik/server/server"
Expand All @@ -27,5 +29,7 @@ func clean(cmd *cobra.Command, args []string) {
plik.WithDataBackend(dataBackend)

// Delete expired upload and files
fmt.Println("Cleaning expired uploads and files...")
plik.Clean()
fmt.Println("Cleaning completed")
}
4 changes: 2 additions & 2 deletions server/cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

// exportCmd to export metadata
var exportCmd = &cobra.Command{
Use: "export",
Use: "export [output-file]",
Short: "Export metadata",
Run: exportMetadata,
}
Expand All @@ -26,7 +26,7 @@ func exportMetadata(cmd *cobra.Command, args []string) {

initializeMetadataBackend()

fmt.Printf("Exporting metadata from %s %s to %s\n", metadataBackend.Config.Driver, metadataBackend.Config.ConnectionString, args[0])
fmt.Printf("Exporting metadata from %s to %s\n", metadataBackend.Config.Driver, args[0])

err := metadataBackend.Export(args[0])
if err != nil {
Expand Down
69 changes: 56 additions & 13 deletions server/cmd/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package cmd

import (
"fmt"
"github.com/root-gg/utils"
"os"

"github.com/root-gg/utils"

"github.com/dustin/go-humanize"
"github.com/spf13/cobra"

Expand All @@ -16,6 +17,7 @@ type fileFlagParams struct {
uploadID string
fileID string
human bool
all bool
}

var fileParams = fileFlagParams{}
Expand All @@ -30,21 +32,32 @@ var fileCmd = &cobra.Command{
var listFilesCmd = &cobra.Command{
Use: "list",
Short: "List files",
Run: listFiles,
Example: ` plikd file list
plikd file list --upload abc123
plikd file list --file def456
plikd file list --human=false`,
Run: listFiles,
}

// showFileCmd represents the "file show" command
var showFileCmd = &cobra.Command{
Use: "show",
Short: "show file info",
Run: showFile,
Use: "show",
Short: "Show file info",
Example: ` plikd file show --file abc123`,
Run: showFile,
}

// deleteFilesCmd represents the "file delete" command
var deleteFilesCmd = &cobra.Command{
// deleteFileCmd represents the "file delete" command
var deleteFileCmd = &cobra.Command{
Use: "delete",
Short: "Delete files",
Run: deleteFiles,
Short: "Delete a file, an upload, or all uploads",
Long: `Delete a file, an upload, or all uploads.

You must specify exactly one of --file, --upload, or --all.`,
Example: ` plikd file delete --file abc123
plikd file delete --upload def456
plikd file delete --all`,
Run: deleteFiles,
}

func init() {
Expand All @@ -58,7 +71,9 @@ func init() {
listFilesCmd.Flags().BoolVar(&fileParams.human, "human", true, "human readable size")

fileCmd.AddCommand(showFileCmd)
fileCmd.AddCommand(deleteFilesCmd)

fileCmd.AddCommand(deleteFileCmd)
deleteFileCmd.Flags().BoolVar(&fileParams.all, "all", false, "delete ALL uploads (requires confirmation)")
}

func listFiles(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -131,6 +146,28 @@ func showFile(cmd *cobra.Command, args []string) {
}

func deleteFiles(cmd *cobra.Command, args []string) {
// Require exactly one of --file, --upload, or --all
flagCount := 0
if fileParams.fileID != "" {
flagCount++
}
if fileParams.uploadID != "" {
flagCount++
}
if fileParams.all {
flagCount++
}

if flagCount == 0 {
fmt.Println("Please specify one of --file, --upload, or --all")
_ = cmd.Usage()
os.Exit(1)
}
if flagCount > 1 {
fmt.Println("Please specify only one of --file, --upload, or --all")
os.Exit(1)
}

initializeMetadataBackend()

if fileParams.fileID != "" {
Expand Down Expand Up @@ -160,6 +197,8 @@ func deleteFiles(cmd *cobra.Command, args []string) {
fmt.Printf("Unable to remove file %s : %s\n", fileParams.fileID, err)
os.Exit(1)
}

fmt.Printf("File %s has been removed\n", fileParams.fileID)
} else if fileParams.uploadID != "" {

// Ask confirmation
Expand All @@ -175,10 +214,12 @@ func deleteFiles(cmd *cobra.Command, args []string) {

err = metadataBackend.RemoveUpload(fileParams.uploadID)
if err != nil {
fmt.Printf("Unable to get upload files : %s\n", err)
fmt.Printf("Unable to remove upload %s : %s\n", fileParams.uploadID, err)
os.Exit(1)
}
} else {

fmt.Printf("Upload %s has been removed\n", fileParams.uploadID)
} else if fileParams.all {

// Ask confirmation
fmt.Printf("Do you really want to remove ALL uploads ? [y/N]\n")
Expand All @@ -199,14 +240,16 @@ func deleteFiles(cmd *cobra.Command, args []string) {
fmt.Printf("Unable to delete uploads : %s\n", err)
os.Exit(1)
}

fmt.Println("All uploads have been removed")
}

// Clean data backend
plik := server.NewPlikServer(config)
plik.WithMetadataBackend(metadataBackend)

initializeDataBackend()
plik.WithDataBackend(dataBackend)

// Delete upload and files
plik.Clean()
}
Loading