Can i bake a texture in headless mode? 2.80
I am doing texture baking in headless mode and it works for me. Not sure what is the problem with your script but here is my script:
import bpy
import logging
import sys

console_handler = logging.StreamHandler(sys.stdout)
log = logging.getLogger(__name__)
log.addHandler(console_handler)

cuda_devices, opencl_devices = bpy.context.preferences.addons['cycles'].preferences.get_devices(
)

bpy.context.scene.render.engine = &quot;CYCLES&quot;
bpy.context.scene.cycles.device = &quot;GPU&quot;
bpy.context.preferences.addons[&quot;cycles&quot;].preferences.compute_device_type = &quot;CUDA&quot;

for device in cuda_devices:
    print(f'Activating {device.name}')
    device.use = True
    break

# need object mode for make_single_user
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.make_single_user(
    type=&quot;ALL&quot;, object=False, obdata=False, material=True)

if 'dynamic' in bpy.data.collections:
    bpy.data.collections['dynamic'].hide_render = True

for object in list(bpy.data.objects):
    if object.active_material is None:
        log.warning(&quot;Object %s doesn't have a material. Skipping.&quot;, object.name)
        continue

    log.info(&quot;Working on %s&quot;, object.name)
    bpy.ops.object.select_all(action='DESELECT')
    object.select_set(True)

    bpy.context.view_layer.objects.active = object
    for slot in object.material_slots:
        if slot.material is None:
            continue

        material = slot.material
        if not material.use_nodes:
            log.warning(
                &quot;Active Material of object %s doesn't use nodes. Skipping.&quot;, object.name)
            continue

        nodes = material.node_tree.nodes

        gltf = None
        shadow = None
        occlusion = None
        for node in nodes.values():
            if node.label == &quot;Shadow&quot;:
                shadow = node
            elif node.label == &quot;Occlusion&quot;:
                occlusion = node
            elif node.type == &quot;GROUP&quot; and node.node_tree and node.node_tree.name == &quot;glTF Metallic Roughness&quot;:
                gltf = node

        if gltf is None:
            log.warning(&quot;Skipping %s: no gltf node defined&quot;, object.name)
            continue

        shadow_input = None
        occlusion_input = None
        for input in gltf.inputs:
            if input.name == &quot;Shadow&quot;:
                shadow_input = input
            elif input.name == &quot;Occlusion&quot;:
                occlusion_input = input

        if shadow_input is None:
            log.warning(
                &quot;Skipping %s: gltf group doesn't define a shadow input&quot;, object.name)
            continue

        if occlusion_input is None:
            log.warning(
                &quot;Skipping %s: gltf group doesn't define a occlusion input&quot;, object.name)
            continue

        shadow = nodes.new(type=&quot;ShaderNodeTexImage&quot;)
        shadow.label = &quot;Shadow&quot;

        occlusion = nodes.new(type=&quot;ShaderNodeTexImage&quot;)
        occlusion.label = &quot;Occlusion&quot;

        shadow_output = shadow.outputs[0]
        occlusion_output = occlusion.outputs[0]

        material.node_tree.links.new(shadow_input, shadow_output)
        material.node_tree.links.new(occlusion_input, occlusion_output)

        image = bpy.data.images.new(&quot;shadow&quot;, 256, 256)
        shadow.image = image

        nodes.active = shadow
        shadow.select = True

        bpy.ops.object.bake(type=&quot;SHADOW&quot;)
        image.pack()
        shadow.select = False

        image = bpy.data.images.new(&quot;occlusion&quot;, 256, 256)
        occlusion.image = image

        nodes.active = occlusion
        occlusion.select = True

        bpy.ops.object.bake(type=&quot;AO&quot;)
        image.pack()
        occlusion.select = False

    object.select_set(False)

bpy.ops.wm.save_mainfile()

You can probably delete like 70% of it or so for your usecase. I am especially unsure if the CUDA stuff in the beginning even works. Also this is highly specific to my use case (all the stuff around the glTF node in there) but maybe it helps you solve your issue.