<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>file_storage.html</title> </head> <body> <h1>File Storage in GitLab</h1> <p>We use the <a href="https://github.com/carrierwaveuploader/carrierwave">CarrierWave</a> gem to handle file upload, store and retrieval.</p> <p>There are many places where file uploading is used, according to contexts:</p> <ul> <li>System <ul> <li>Instance Logo (logo visible in sign in/sign up pages)</li> <li>Header Logo (one displayed in the navigation bar)</li> </ul> </li> <li>Group <ul> <li>Group avatars</li> </ul> </li> <li>User <ul> <li>User avatars</li> <li>User snippet attachments</li> </ul> </li> <li>Project <ul> <li>Project avatars</li> <li>Issues/MR/Notes Markdown attachments</li> <li>Issues/MR/Notes Legacy Markdown attachments</li> <li>CI Build Artifacts</li> <li>LFS Objects</li> </ul> </li> </ul> <h2>Disk storage</h2> <p>GitLab started saving everything on local disk. While directory location changed from previous versions, they are still not 100% standardized. You can see them below:</p> <table> <thead> <tr> <th> Description </th> <th> In DB? </th> <th> Relative path </th> <th> Uploader class </th> <th> model_type </th> </tr> </thead> <tbody> <tr> <td> Instance logo </td> <td> yes </td> <td> uploads/-/system/appearance/logo/:id/:filename </td> <td> <code>AttachmentUploader</code> </td> <td> Appearance </td> </tr> <tr> <td> Header logo </td> <td> yes </td> <td> uploads/-/system/appearance/header_logo/:id/:filename </td> <td> <code>AttachmentUploader</code> </td> <td> Appearance </td> </tr> <tr> <td> Group avatars </td> <td> yes </td> <td> uploads/-/system/group/avatar/:id/:filename </td> <td> <code>AvatarUploader</code> </td> <td> Group </td> </tr> <tr> <td> User avatars </td> <td> yes </td> <td> uploads/-/system/user/avatar/:id/:filename </td> <td> <code>AvatarUploader</code> </td> <td> User </td> </tr> <tr> <td> User snippet attachments </td> <td> yes </td> <td> uploads/-/system/personal_snippet/:id/:random_hex/:filename </td> <td> <code>PersonalFileUploader</code> </td> <td> Snippet </td> </tr> <tr> <td> Project avatars </td> <td> yes </td> <td> uploads/-/system/project/avatar/:id/:filename </td> <td> <code>AvatarUploader</code> </td> <td> Project </td> </tr> <tr> <td> Issues/MR/Notes Markdown attachments </td> <td> yes </td> <td> uploads/:project_path_with_namespace/:random_hex/:filename </td> <td> <code>FileUploader</code> </td> <td> Project </td> </tr> <tr> <td> Issues/MR/Notes Legacy Markdown attachments </td> <td> no </td> <td> uploads/-/system/note/attachment/:id/:filename </td> <td> <code>AttachmentUploader</code> </td> <td> Note </td> </tr> <tr> <td> CI Artifacts (CE) </td> <td> yes </td> <td> shared/artifacts/:year_:month/:project_id/:id </td> <td> <code>ArtifactUploader</code> </td> <td> Ci::Build </td> </tr> <tr> <td> LFS Objects (CE) </td> <td> yes </td> <td> shared/lfs-objects/:hex/:hex/:object_hash </td> <td> <code>LfsObjectUploader</code> </td> <td> LfsObject </td> </tr> </tbody> </table> <p>CI Artifacts and LFS Objects behave differently in CE and EE. In CE they inherit the <code>GitlabUploader</code> while in EE they inherit the <code>ObjectStoreUploader</code> and store files in and S3 API compatible object store.</p> <p>In the case of Issues/MR/Notes Markdown attachments, there is a different approach using the <a href="../administration/repository_storage_types.md">Hashed Storage</a> layout, instead of basing the path into a mutable variable <code>:project_path_with_namespace</code>, it’s possible to use the hash of the project ID instead, if project migrates to the new approach (introduced in 10.2).</p> </body> </html>