I encountered an issue where I was running gitea in a docker instance, and migrated it to a new subdomain. I had setup U2F / WebAuthn before the migration, and neglected to disable it prior to the migration. After having set up Caddy and Tailscale etc, I realised that I didn’t have access via the web interface anymore (due to U2F being locked to domain name). I thought it may be easier to reset the MFA than to migrate back to the old subdomain, but realised that there wasn’t really any well documented way of doing this (that I could find). There are a few issues on Github that kind of deal with this, but nothing really definitive, so I set about exploring.

Here are the brief notes of what I did, in case you need to do similarly. My setup was using the default gitea/gitea:latest image.

  • Enter your docker container with docker exec -it gitea /bin/bash
  • su to your git user with su git
  • Assuming you are also running sqlite3 with the default database, enter its command prompt:
35dd2a574ef5:/$ sqlite3 /data/gitea/gitea.db
SQLite version 3.41.2 2023-03-22 11:56:21
Enter ".help" for usage hints.
sqlite> 
  • Make sure you can see all tables:
sqlite> SELECT name FROM sqlite_schema WHERE type='table' ORDER BY name;
access
access_token
action
action_artifact
action_run
action_run_index
action_run_job
action_runner
action_runner_token
action_task
action_task_output
action_task_step
app_state
attachment
badge
collaboration
comment
commit_status
commit_status_index
dbfs_data
dbfs_meta
deleted_branch
deploy_key
email_address
email_hash
external_login_user
follow
gpg_key
gpg_key_import
hook_task
issue
issue_assignees
issue_content_history
issue_dependency
issue_index
issue_label
issue_user
issue_watch
label
language_stat
lfs_lock
lfs_meta_object
login_source
milestone
mirror
notice
notification
o_auth2_application
oauth2_application
oauth2_authorization_code
oauth2_grant
oauth2_session
org_user
package
package_blob
package_blob_upload
package_cleanup_rule
package_file
package_property
package_version
project
project_board
project_issue
protected_branch
protected_tag
public_key
pull_auto_merge
pull_request
push_mirror
reaction
release
renamed_branch
repo_archiver
repo_indexer_status
repo_redirect
repo_topic
repo_transfer
repo_unit
repository
review
review_state
secret
session
sqlite_sequence
star
stopwatch
system_setting
task
team
team_invite
team_repo
team_unit
team_user
topic
tracked_time
two_factor
u2_f_registration
u2f_registration
upload
user
user_badge
user_open_id
user_redirect
user_setting
version
watch
webauthn_credential
webhook
  • Inspect your tables to make sure they have content:
sqlite> SELECT * FROM 'u2f_registration';
1|Yubikey 5|SNIPPED
3|Yubi5ci|SNIPPED

sqlite> SELECT * FROM 'webauthn_credential';
"X kHle|apple|1|SNIPPED
  • Finally, delete the content of these and you will be able to login:
sqlite> DELETE FROM 'two_factor';
sqlite> DELETE FROM 'u2f_registration';
sqlite> DELETE FROM 'webauthn_credential';