{"id":24093231,"url":"https://github.com/umd-lib/umd-web-static-files","last_synced_at":"2026-02-12T19:02:30.209Z","repository":{"id":147003296,"uuid":"301465785","full_name":"umd-lib/umd-web-static-files","owner":"umd-lib","description":"Provided Docker image configuration for serving static web application files.","archived":false,"fork":false,"pushed_at":"2023-05-12T11:22:48.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":13,"default_branch":"develop","last_synced_at":"2025-08-13T21:46:50.907Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/umd-lib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-05T16:06:19.000Z","updated_at":"2023-05-12T11:22:53.000Z","dependencies_parsed_at":"2025-02-27T11:04:56.905Z","dependency_job_id":"cf542be0-ed5d-4831-b965-714fc623c9c9","html_url":"https://github.com/umd-lib/umd-web-static-files","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/umd-lib/umd-web-static-files","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umd-lib%2Fumd-web-static-files","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umd-lib%2Fumd-web-static-files/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umd-lib%2Fumd-web-static-files/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umd-lib%2Fumd-web-static-files/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/umd-lib","download_url":"https://codeload.github.com/umd-lib/umd-web-static-files/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umd-lib%2Fumd-web-static-files/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29377911,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T18:59:55.292Z","status":"ssl_error","status_checked_at":"2026-02-12T18:59:44.289Z","response_time":55,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-10T09:26:18.562Z","updated_at":"2026-02-12T19:02:30.194Z","avatar_url":"https://github.com/umd-lib.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UMD Web Static Files\n\nRespository for creating a Docker image that holds default versions of commonly\nused \"static files\" for web applications, such as:\n\n* favicon.ico\n* Google Site Verification HTML file\n* robots.txt\n* sitemap.xml\n\nThe Docker image uses a simple Nginx-based container, providing a generic\nmechanism for accessing these files in a Kubernetes stack.\n\nThe \"robots.txt\" and \"sitemap.xml\" files are \"default closed\", i.e., the\n\"robots.txt\" does not allow crawling, and the \"sitemap.xml\" is empty.\n\nThe files are provided in separate subdirectories so that a Kubernetes overlay\ncan override each file individually.\n\n## Repository Files\n\n### Dockerfile\n\nThe \"Dockerfile\" is used to build the Docker image.\n\n```\n\u003e docker build -t docker.lib.umd.edu/umd-web-static-files:\u003cVERSION\u003e -f Dockerfile .\n```\n\nwhere \\\u003cVERSION\u003e is the Docker image version to create.\n\nThe resulting Docker image should then be pushed to the Nexus.\n\n### docker_config/nginx/\n\nContains the configuration for the Nginx server.\n\n### static-files/\n\nThis directory contains a subdirectory for each file being served. The files\nare organized in this manner, so that the files can be overridden indvidually\nby a Kubernetes configuration.\n\nThe \"google-file-upload\" directory contains the HTML file for use with the\n\"HTML file upload\" verification method provided by Google.\nSee [https://support.google.com/webmasters/answer/9008080](https://support.google.com/webmasters/answer/9008080).\n\n## Kubernetes Configuration\n\nThe following is an example of using the \"umd-web-static-files\" image in\na Kubernetes configuration following the layout in\n[\"k8s-new-app\"](https://github.com/umd-lib/k8s-new-app).\n\nIn the following examples, the name of the application is \"foobar\". The files\nwill be served at the following URLs:\n\n* https://foobar.lib.umd.edu/favicon.ico\n* https://foobar.lib.umd.edu/googlee5878e862cad1cec.html\n* https://foobar.lib.umd.edu/robots.txt\n* https://foobar.lib.umd.edu/sitemap.xml\n\n## Changes to the \"base\" overlay\n\nThe \"base\" overlay sets up the \"foobar-static-files\" pod running the\n\"umd-web-static-files\" image.\n\n### base/deployment.yaml\n\nThe following creates a \"foobar-static-files\" Deployment, with an associated\n\"foobar-static-files\" pod.\n\nThe deployment uses the \"umd-web-static-files\" Nginx Docker image\n(docker.lib.umd.edu/umd-web-static-files:latest), which serves a default set\nof files from the \"/usr/share/nginx/html\" directory. Each file is in it's own\nsubdirectory, so it can be overridden by the overlays:\n\n* favicon/favicon.ico\n* google-file-upload/googlee5878e862cad1cec.html\n* robots/robots.txt\n* sitemap/sitemap.xml\n\nThe liveness probe use the \"robots.txt\" file for determining pod status.\n\n```\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: foobar-static-files\n  labels: \u0026foobar-static-files-labels\n    app: foobar-static-files\n    app.kubernetes.io/instance: foobar\n    app.kubernetes.io/name: static-files\n    app.kubernetes.io/component: static-files\nspec:\n  # Configure replication factor for the pod, if more than one\n  replicas: 1\n\n  # To link the pod to deployment\n  selector:\n    matchLabels:\n      app: foobar-static-files\n\n  template:\n    # Metadata for the Pod template\n    metadata:\n      # Labels for the pod\n      labels: \u0026foobar-static-files-labels\n        app: foobar-static-files\n    spec:\n      imagePullSecrets:\n        - name: regcred\n      # Container Configuration\n      containers:\n      - image: docker.lib.umd.edu/umd-web-static-files:latest\n        name: foobar-static-files\n        # Resource configuration\n        resources:\n          # Minimum necessary to schedule the pod to a node\n          requests:\n            memory: \"1Mi\"\n            cpu: \"1m\"\n          # Max allowed\n          limits:\n            memory: \"512Mi\"\n            cpu: \"1000m\"\n        # Ports to open on a container\n        ports:\n        - containerPort: 80\n          name: http\n          protocol: TCP\n        # Using robots.txt to verify liveness\n        livenessProbe:\n          httpGet:\n            path: /robots.txt\n            port: 80\n          initialDelaySeconds: 10\n          periodSeconds: 120\n          timeoutSeconds: 5\n```\n\n### base/service.yaml\n\nThe following addition to the \"base/service.yaml\" file enables port 80 on the\n\"foobar-static-files\" pod to be accessed:\n\n```\n---\n# foobar static files\napiVersion: v1\nkind: Service\nmetadata:\n  name: foobar-static-files\nspec:\n  selector:\n    app: foobar-static-files\n  ports:\n  - protocol: TCP\n    port: 80\n    targetPort: 80\n    name: http\n```\n\n### base/networkpolicy.yaml\n\nThe following addition to the \"base/networkpolicy.yaml\" allows enables port 80 on\nthe \"foobar-static-files\" pod to be reached from anywhere:\n\n```\n---\n# Allow external HTTP traffic (ingress) to foobar-static-files pod\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  name: foobar-allow-external-http-to-static-files\nspec:\n  podSelector:\n    matchLabels:\n      app: foobar-static-files\n  policyTypes:\n  - Ingress\n  ingress:\n  - from: []\n    ports:\n      - port: 80\n```\n\n### base/ingress.yaml\n\nThe base/ingress.yaml file is changed to pass the following URL paths to the \"foobar-static-files\" pod, instead of to the \"foobar-app\" pod running the web application:\n\n* /favicon.ico\n* /googlee5878e862cad1cec.html\n* /robots.txt\n* /sitemap.xml\n\nAll other URL paths go to the \"foobar-app\" pod.\n\n----\n\n**WARNING**\n\nIn the stock \"k8s-new-app\" example application, the \"base/ingress.yaml\" file\ncontains the following \"rewrite\" annotation in \"Ingress\" configurations:\n\n```\napiVersion: networking.k8s.io/v1beta1\nkind: Ingress\nmetadata:\n  ...\n  annotations:\n    ...\n    # Rewrite requests if training slash missing (/search -\u003e /search/)\n    nginx.ingress.kubernetes.io/rewrite-target: \"/\"\n```\n\nthe \"rewrite\" annotation MUST be removed, as it forcibly rewrites all URL paths\npassed to the \"foobar-static-files\" pod to \"/\" (i.e. \"/robots.txt\" gets\nre-written to \"/\").\n\nIt is not clear if this rewrite rule is actually helpful in any way, so\nremoving it should not cause a problem.\n\n----\n\n```\n# Ingress configuration to expose Foobar public interface to internet\napiVersion: networking.k8s.io/v1beta1\nkind: Ingress\nmetadata:\n  name: foobar-public-ingress\n\n  labels:\n    app.kubernetes.io/instance: foobar-public\n\n  # See all available annotations:\n  #  https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/\n  annotations:\n    # Let's Encrypt certificate provisioning\n    # Use \"letsencrypt-staging\" as the cluster-issuer if you will testing\n    # multiple issues of certificates\n    kubernetes.io/ingress.class: \"nginx\"\n    cert-manager.io/cluster-issuer: \"letsencrypt\"\n\nspec:\n  tls:\n  - hosts:\n    - \u003cFoobar public domain_name\u003e\n    secretName: \u003cFoobar public domain_name\u003e-tls-secret\n  rules:\n  - host: \u003cdomain_name\u003e\n    http:\n      paths:\n      - path: /\n        backend:\n          serviceName: foobar-app\n          servicePort: 8081\n#----- The following lines are added -----\n      - path: /favicon.ico\n        pathType: Exact\n        backend:\n          service:\n           name: foobar-static-files\n           port:\n             number: 80\n      - path: /googlee5878e862cad1cec.html\n        pathType: Exact\n        backend:\n          service:\n            name: foobar-static-files\n            port:\n              number: 80\n      - path: /robots.txt\n        pathType: Exact\n        backend:\n          service:\n            name: foobar-static-files\n            port:\n              number: 80\n      - path: /sitemap.xml\n        pathType: Exact\n        backend:\n          service:\n            name: foobar-static-files\n            port:\n              number: 80\n#-----------------------------------------\n```\n\n## Overriding Files in overlays\n\nIf no changes are needed to the static files provided in the \"base\", then\nnothing needs to be added to an overlay, as it will get the files in the\n\"base\" by default.\n\nFiles are overridden by using a \"configMapGenerator\" in the \"kustomization.yaml\"\nfile in the overlay, which generates a ConfigMap, and a \"patch\" file to the\nDeployment in the \"base\".\n\n### Add the overridden versions of the files\n\nThe static files that are being overridden should be added to an\n\"overlays/\\\u003cENV\u003e/static-files\" directory, where \"\\\u003cENV\u003e\" is the environment.\nFor example, override the \"robots/robots.txt\" and \"sitemap/sitemap.xml\" files\nin the \"prod\" overlay, create the following file hierarchy:\n\n```\nk8s-foobar/\n   |-- overlays/\n         |-- prod/\n               |-- static-files/\n                     |-- robots/\n                           |-- robots.txt\n                     |-- sitemap/\n                           |-- sitemap.xml\n```\n\n\n### overlays/\\\u003cENV\u003e/deployment-patch.yaml\n\nA \"deployment-patch.yaml\" file adds the \"volumes\" and \"volumeMounts\" for the\noverridden files:\n\n```\n- op: add\n  path: /spec/template/spec/containers/0/volumeMounts/-\n  value:\n    name: static-files-volume-robots\n    mountPath: \"/usr/share/nginx/html/robots\"\n    readOnly: true\n- op: add\n  path: /spec/template/spec/volumes/-\n  value:\n    name: static-files-volume-robots\n    configMap:\n      # Provide the name of the ConfigMap you want to mount.\n      name: foobar-static-files-robots-config\n      # An array of keys from the ConfigMap to create as files\n      items:\n      - key: \"robots.txt\"\n        path: \"robots.txt\"\n- op: add\n  path: /spec/template/spec/containers/0/volumeMounts/-\n  value:\n    name: foobar-files-volume-sitemap\n    mountPath: \"/usr/share/nginx/html/sitemap\"\n    readOnly: true\n- op: add\n  path: /spec/template/spec/volumes/-\n  value:\n    name: static-files-volume-sitemap\n    configMap:\n      # Provide the name of the ConfigMap you want to mount.\n      name: foobar-static-files-sitemap-config\n      # An array of keys from the ConfigMap to create as files\n      items:\n      - key: \"sitemap.xml\"\n        path: \"sitemap.xml\"\n```\n\n### overlays/\\\u003cENV\u003e/kustomization.yaml\n\nThe following \"configMapGenerator\" in the \"overlays/\\\u003cENV\u003e/kustomization.yaml\"\nfile adds ConfigMaps for the two files being overriden, while the\n\"patchesJson6902\" ensures that the \"deployment-patch.yaml\" file is used to\nmodify the \"base/deployment.yaml\" file:\n\n```\nconfigMapGenerator:\n- name: foobar-static-files-robots-config\n  files:\n     - static-files/robots/robots.txt\n- name: foobar-static-files-sitemap-config\n  files:\n     - static-files/sitemap/sitemap.xml\n\npatchesJson6902:\n  - path: deployment-patch.yaml\n    target:\n      group: apps\n      version: v1\n      kind: Deployment\n      name: foobar-static-files\n```\n\n## Variations for Special Cases\n\nThe above section describes a complete configuration for a web application. The\nfollowing are variations for the above for specific circumstances.\n\n### Public/Staff interface in same application, but on different URLs\n\nExample: ArchivesSpace (https://github.com/umd-lib/k8s-aspace)\n\nIn ArchivesSpace, there is a \"public\" interface at https://archives.lib.umd.edu/\nand a \"staff\" interface at https://aspace.lib.umd.edu/. Both URLs are served\nfrom the same web application.\n\nIn production, the \"robots.txt\" for the public interface should allow crawling,\nwhile the \"robots.txt\" for the staff interface should not. Similarly, only the\n\"sitemap.xml\" for the \"public\" interface should be populated.\n\nThis was implemented as follows:\n\n1) In the \"base\" overlay, created a \"base/static-files/extra/\" directory, and\nadded \"robots-public.txt\" and \"sitemap-public.xml\" to it:\n\n```\nbase/\n  |-- static-files/\n        |-- extra/\n              |-- robots-public.txt\n              |-- sitemap-public.xml\n```\n\nThese file are the same as \"robots.txt\" and \"sitemap.xml\" files in\n\"umd-web-static-files\", as they are \"default closed\". The actual production\nversions will be in the \"prod\" overlay.\n\n2) Modified \"base/configmap.yaml\", adding a \"aspace-static-files-extra-config\"\nConfigMap:\n\n```\n---\n# Static files configmap\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: aspace-static-files-extra-config\n```\n\n3) Modified \"base/deployment.yaml\" to include the additional static files:\n\n```\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: aspace-static-files\n  ...\n  spec:\n    ...\n    template:\n      ...\n      spec:\n        ...\n        containers\n        ...\n          volumeMounts:\n          - name: static-files-volume-extra\n            mountPath: \"/usr/share/nginx/html/extra\"\n            readOnly: true\n        volumes:\n          # You set volumes at the Pod level, then mount them into containers inside that Pod\n          - name: static-files-volume-extra\n            configMap:\n              # Provide the name of the ConfigMap you want to mount.\n              name: aspace-static-files-extra-config\n              # An array of keys from the ConfigMap to create as files\n              items:\n              - key: \"robots-public.txt\"\n                path: \"robots-public.txt\"\n              - key: \"sitemap-public.xml\"\n                path: \"sitemap-public.xml\"\n```\n\n4) Modified \"base/kustomization.yaml\" to add the additional static files to the \"configMapGenerator\" stanza:\n\n```\n# Configs to generate and link to the base resources\nconfigMapGenerator:\n- name: aspace-static-files-extra-config\n  behavior: merge\n  files:\n    - static-files/extra/robots-public.txt\n    - static-files/extra/sitemap-public.xml\n```\n\n5) In \"base/ingress.yaml\", added the followng rewrite rules to the ArchivesSpace public interface:\n\n```\n# Ingress configuration to expose ArchivesSpace public interface to internet\napiVersion: networking.k8s.io/v1beta1\nkind: Ingress\nmetadata:\n  name: aspace-public-ingress\n  ...\n  annotations:\n    ...\n    # Rewrite rules to force public interface to use \"public\" versions\n    # of robots.txt and sitemap.xml files\n    #\n    # Needed because \"public\" and \"staff\" interfaces are on different URLs\n    # and require different robots.txt and sitemap.xml files\n    nginx.ingress.kubernetes.io/configuration-snippet: |\n        rewrite ^/sitemap.xml$ /extra/sitemap-public.xml break;\n        rewrite ^/robots.txt$ /extra/robots-public.txt break;\n```\n\n6) In the \"prod\" overlay, add a \"static-files/extra/\" directory, with the \"robots-public.txt\" and \"sitemap-public.xml\" that are actually to be used on the production server:\n\n```\nprod/\n  |-- static-files/\n        |-- extra/\n              |-- robots-public.txt\n              |-- sitemap-public.xml\n```\n\n7) In the \"prod/kustomization.yaml\" file, add a \"configMapGenerator\" to merge the files into the \"base\" overlay (if a \"configMapGenerator\" stanza already exists, add all the lines except \"configMapGenerator\"):\n\n```\nconfigMapGenerator:\n...\n- name: aspace-static-files-extra-config\n  behavior: merge\n  files:\n    - static-files/extra/robots-public.txt\n    - static-files/extra/sitemap-public.xml\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fumd-lib%2Fumd-web-static-files","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fumd-lib%2Fumd-web-static-files","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fumd-lib%2Fumd-web-static-files/lists"}