When I was researching how to migrate local storage in Gitea to S3/Minio, I couldn’t find anything in their official documentation that would let me do it.

However, today I’ve learned about an undocumented command called migrate-storage which does exactly that. It appears that they’ve merged pull requests that fix bugs with the command (see go-gitea/gitea#20566 and go-gitea/gitea#28728), so I think they just forgot to document it.

Based on #28728, you can migrate the storage currently configured in the app.ini to Minio with this bash script for Gitea v1.22:

for DATATYPE in attachments lfs avatars repo-avatars repo-archivers packages actions-log actions-artifacts; do
    echo DATATYPE=$DATATYPE;
	gitea migrate-storage \
        --type=$DATATYPE \
        --minio-base-path=$DATATYPE \
        --storage=minio \
        --minio-endpoint=$MINIO_ENDPOINT \
        --minio-access-key-id=$MINIO_ACCESS_KEY_ID \
        --minio-secret-access-key=$MINIO_SECRET_ACCESS_KEY \
        --minio-bucket=$MINIO_BUCKET \
        --minio-location=$MINIO_LOCATION \
        --minio-use-ssl=true
done

You may have to rename the actions-log and actions-artifacts to actions_log and actions_artifacts respectively depending on how your paths are configured in Gitea.

The help output for the migrate-storage command reads as follows:

NAME:
   gitea migrate-storage - Migrate the storage

USAGE:
   gitea migrate-storage command [command options] 

DESCRIPTION:
   Copies stored files from storage configured in app.ini to parameter-configured storage

COMMANDS:
   help, h  Shows a list of commands or help for one command

OPTIONS:
   --help, -h                        show help
   --custom-path value, -C value     Set custom path (defaults to '{WorkPath}/custom')
   --config value, -c value          Set custom config file (defaults to '{WorkPath}/custom/conf/app.ini')
   --work-path value, -w value       Set Gitea's working path (defaults to the Gitea's binary directory)
   --type value, -t value            Type of stored files to copy.  Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log', 'actions-artifacts
   --storage value, -s value         New storage type: local (default) or minio
   --path value, -p value            New storage placement if store is local (leave blank for default)
   --minio-endpoint value            Minio storage endpoint
   --minio-access-key-id value       Minio storage accessKeyID
   --minio-secret-access-key value   Minio storage secretAccessKey
   --minio-bucket value              Minio storage bucket
   --minio-location value            Minio storage location to create bucket
   --minio-base-path value           Minio storage base path on the bucket
   --minio-use-ssl                   Enable SSL for minio (default: false)
   --minio-insecure-skip-verify      Skip SSL verification (default: false)
   --minio-checksum-algorithm value  Minio checksum algorithm (default/md5)